Rails'ActiveRecord::Base
类定义了==
方法,如果对象相同或ID相同,则返回true
。
我已经在我的几个Rails模型中覆盖了==
,以允许更有意义的平等条件。这些工作在我直接比较对象时起作用(例如,通过script/console
),但如果我执行my_array_of_models.include? other_model
之类的操作,则include?
始终返回false
。即使数组包含一个“相等”的对象(根据我的定义)。
我已经通过这样做来解决这个问题,例如my_array_of_models.any? { |el| el.attr == other_model.attr }
(我认为这是鼓励你进行比较的方式),但我想知道:覆盖{{1是否有意义在ActiveRecord模型中,还是ActiveRecord做了一些高级别的事情,使得这种被覆盖的方法变得无用(或者更糟,更危险)?
这是我重写的方法的实现。有两个类==
和User
。 Contact
具有唯一的电子邮件地址,因此如果电子邮件地址相同,则Users
会返回true。 ==
是Contact
之间的桥梁(就像社交网络中的“朋友”关系),如果它们具有相同的Users
,则应该返回true
。
user_id
正如我所指出的,它直接比较时有用(例如class User < ActiveRecord::Base
def ==(other)
other.respond_to?(:email) and self.email == other.email
end
end
class Contact < ActiveRecord::Base
def ==(other)
if other.class == self.class
self.user == other.user
elsif other.kind_of? User
self.user == other
else
false
end
end
end
),但one_object == another_object
总是返回my_array_of_objs.include? included_obj
。
答案 0 :(得分:0)
阅读这篇文档也许是有益的:
http://ruby-doc.org/core/classes/Object.html#M000341
array_of_models.include?(my_object)
可能不起作用,因为==
不用于测试集合是否包含对象。它使用equal?
。
修改
OP的断言即使他为模型覆盖==
方法,array.include?(obj)
返回false也不是真的。让我们看看:
class Event < ActiveRecord::Base
def ==(that)
if(that.eventname == self.eventname)
true
else
false
end
end
end
>> a << Event.find(1)
=> [#<Event id: 1, eventname: "hemant", foo: nil, created_at: "2009-06-24 21:33:00", updated_at: "2009-06-24 21:33:00">]
>> b = Event.find(2)
=> #<Event id: 2, eventname: "hemant", foo: nil, created_at: "2009-06-24 21:33:04", updated_at: "2009-06-24 21:33:04">
>> a.include?(b)
=> true
显然这不是真的。但无论如何,我认为由于AR以特定方式定义==
,因此覆盖它并不是一个好主意。它可能导致难以发现错误。
答案 1 :(得分:0)
说明问题的另一种方式可能是“= ='方法被认为是'最终'?”。在Java中,您可以使用'final'关键字来防止在子类中重写方法(您也可以将final应用于类,因此它们根本不能被子类化)。这在OO设计中可能是一个方便的东西,因为某些类或方法不是为了被覆盖而设计的。当然,Ruby没有'final',但是这里可能存在相同的概念(也许你甚至可以使用元编程来实现它)。
我记得在OO中使用'final'阅读一些好的文章和/或SO帖子。如果我找到它们,我会编辑它们。
答案 2 :(得分:0)
ActiveRecord模型是一个实体对象。根据设计,它表示数据库中的一行,id
列是在数据库级别唯一标识它的主键。
正如Hemant Kumar所指出的那样,你可以覆盖它,但是通过这样做,具有不同id的对象被认为是相同的,但这不是真的。
此次更改时,设计从ActiveRecord实体对象转移到纯值对象。
您的问题的可能解决方案是:
Rails故意将相等性检查委托给标识列。 如果你想知道两个AR对象是否包含相同的东西,请进行比较 在两者上调用#attributes的结果。
https://stackoverflow.com/a/4738485/2987689
这个问题还有另一个好方法(https://stackoverflow.com/a/7098377/2987689)