我有两个User对象应该是相同的,但ruby说它们不是。任何人都可以向我解释这里发生了什么?
a = current_user
b = votable.user
a == b
false
a.id == b.id
true
a.name == b.name
true
a.attributes == b.attributes
true
a.class == b.class AKA a.type == b.type
false (note: this is a correction to the original post which said true)
a.class.to_s
"User"
b.class.to_s
"User"
a.class.name == b.class.name
true
a.class.methods == b.class.methods
true
a.class.object_id == b.class.object_id
false
因此对象的类(类型)看起来完全相同。据说是用户。但是当你评估a.class == b.class时,答案是假的,我渲染页面的时间是30%,导致问题。
谁能告诉我发生了什么事?非常感谢。
➜~ruby--version
ruby 1.8.7(2010-01-10 patchlevel 249)[universal-darwin11.0]
➜〜rails --version
Rails 3.0.10
答案 0 :(得分:3)
如果a == b
为假,那么我猜它正在做类似a.object_id == b.object_id
的事情,只有当引用指向同一个对象时才会这样。
a.id == b.id
可能只是检查User.id
,这是有道理的。
最简单的方法是继续检查User.id
。如果你真的想使用==
,你需要在User类中覆盖它,例如:
class User
def ==(other)
self.id == other.id
end
end
答案 1 :(得分:0)
我不知道这些是什么类型的物体。从Object
开始,他们是否合适?
Object#==
并定义更合适的行为,否则 Object#===
确实只是#==
。要使Object#==
=为真,它们必须实际上是对同一对象的引用,而不是对等对象。
只需定义#==
方法并使用一些合理的逻辑来确定两个对象是否相同......然后您可以使用a == b
并获取true
。
如果这些是ActiveRecord::Base
个后代,则会发生其他事情,因为ActiveRecord::Base
个对象确实有一个合理的#==
方法(尽管你也可以覆盖这种行为)。
答案 2 :(得分:0)
这两个对象不是同一个对象。但是,它们引用了数据库中的同一用户。
我建议您在id
上比较它们。
答案 3 :(得分:0)
如果您正在使用Rails 3并假设您的上述每个方法都返回一个ActiveRelation(或至少其中一个返回)。然后可以肯定地说第一次比较是正确的,因为每个ActiveRelation可能是一个不同的对象。
我的回答对您的代码做了一些假设,但可能有助于提供一些见解。
答案 4 :(得分:0)
根据http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-3D-3D的Rails文档,相等运算符应该检查类型和id。
# File activerecord/lib/active_record/base.rb, line 1811
def ==(comparison_object)
super ||
comparison_object.instance_of?(self.class) &&
id.present? &&
comparison_object.id == id
end
必须发生的是他们不是同一个班级。你能检查并输出结果吗?
votable.user.class
current_user.class
答案 5 :(得分:-2)
逻辑解释:
他们有相似的属性,但它们本质上是不同的。请注意,地球和Marth是不同的行星,即使我们只看到它们都在银河系中并且它们都是行星的事实。
如果一个物体就像另一个物体,它不一定相同。
技术说明:
创建对象时,将创建对象的引用。如果您创建另一个对象,则会创建另一个引用。
如果您有对象A和对象。
a = current_user
b = votable.user
a == b
false
a = current_user
b = a
a== b
true
如果它们的引用相同,则两个对象是相同的(当然它们的属性也相同)。如果标准关系不够,你总是可以编写方法来定义新的等价关系;)