从实例方法调用中初始化
Initialize from within instance method call
在我的 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
此 returns TypeError (nil is not a symbol nor a string)
for @field
inside new_item
方法,因为 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_item
和 current_item
return 所需的输出?
- 如何在
.eql?
方法中调用initialize
方法?
- 是否有替代方法?
- 有没有一种方法可以访问类似于
before_action
(在控制器中)的模块中的参数?
您不能实例化模块的实例。 (您可以实例化 class 的实例,但不能实例化 模块 。)
事实上,您在这里实际做的是覆盖Item#initialize
的定义!!
坚持您的一般设计模式,我建议将此逻辑抽象为 新的 class - 例如 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
在我的 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
此 returns TypeError (nil is not a symbol nor a string)
for @field
inside new_item
方法,因为 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_item
和current_item
return 所需的输出? - 如何在
.eql?
方法中调用initialize
方法? - 是否有替代方法?
- 有没有一种方法可以访问类似于
before_action
(在控制器中)的模块中的参数?
您不能实例化模块的实例。 (您可以实例化 class 的实例,但不能实例化 模块 。)
事实上,您在这里实际做的是覆盖Item#initialize
的定义!!
坚持您的一般设计模式,我建议将此逻辑抽象为 新的 class - 例如 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