从实例方法调用内部初始化



在我的Rails应用程序。我有一个模块,我重写.eql?方法如下

# lib/item_util.rb
module ItemUtil
def eql?(item, field: "cost", op: "==")
item.send(field).present? &&
item.send(field).send(op, self.send(field))
end
end

包含在Item模型

# app/models/item.rb
class Item < ApplicationRecord
include ItemUtil
end

在我的控制器中,我想根据属性值检查各种条件。例:

@item1 = Item.find(:id)
@item2 = Item.find(:id)
@item1.eql?(@item2, field: "discount", op: ">") # @item2.discount > @item1.discount
@item2.eql?(@item1, op: "<=") # @item1.cost <= @item2.cost
# ...

这一切都很好,我想写ItemUtil模块在一个更整洁的方式如下:

module ItemUtil
attr_accessor :item, :field
def initialize(item, field: "cost")
@item = item
@field = field
end
def eql?(item, field: "cost", op: "==")
new_item.present? && new_item.send(op, current_item)
end
def new_item
@item.send(@field)
end
def current_item
self.send(@field)
end
end

new_item方法中为@field返回TypeError (nil is not a symbol nor a string),因为initialize没有在任何地方调用

Traceback (most recent call last):
2: from lib/item_util.rb:12:in `eql?'
1: from lib/item_util.rb:17:in `new_item'
TypeError (nil is not a symbol nor a string)

但是我不想改变对象上调用.eql?的方式,也就是说,我想保持这些行完整

@item1.eql?(@item2, field: "discount", op: ">") # @item2.discount > @item1.discount
@item2.eql?(@item1, op: "<=") # @item1.cost <= @item2.cost
  • 我如何得到new_itemcurrent_item返回所需的输出?
  • 如何在.eql?方法中调用initialize方法?
  • 有其他方法吗?
  • 有办法访问参数模块类似于before_action(控制器)?

你不能实例化一个模块的实例。(你可以实例化一个类的实例,但不能实例化一个模块)

实际上,你在这里做的是重写Item#initialize的定义!!

与您的一般设计模式一样,我建议将此逻辑抽象为新类-例如,ItemComparator:
class ItemComparator
attr_reader :item, :other
def initialize(item, other)
@item = item
@other = other
end
def eql?(field:, op:)
item_field = item.send(field)
other_field = other.send(:field)
other_field.present? && item_field.send(op, other_field)
end
end
module ItemUtil
def eql?(other, field: "cost", op: "==")
ItemComparator.new(self, other).eql?(field: field, op: op)
end
end
class Item < ApplicationRecord
include ItemUtil
end

相关内容

  • 没有找到相关文章

最新更新