【发布时间】:2021-10-12 10:09:07
【问题描述】:
在我的 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_item和current_item返回所需的输出? - 如何在
.eql?方法中调用initialize方法? - 是否有替代方法?
- 有没有办法访问类似于
before_action(在控制器中)的模块中的参数?
【问题讨论】:
-
请注意,相等应该是对称的,即
a.eql?(b)通常暗示b.eql?(a)。这不再是您实现eql?的方式。 -
我决定将其重命名为
.compare?
标签: ruby-on-rails ruby ruby-on-rails-6.1