【问题标题】:ActiveRecord object equalityActiveRecord 对象相等
【发布时间】:2011-07-16 16:12:30
【问题描述】:

根据ActiveRecord::Base的文档:

==(comparison_object) 如果 compare_object 完全相同,则返回 true 对象,或 comparison_object 属于 相同的类型和自我有一个ID,它是 等于 compare_object.id。

请注意,新记录是不同的 根据定义,来自任何其他记录, 除非另一条记录是 接收机本身。此外,如果你取 带有选择和离开的现有记录 ID出来了,你自己一个人,这个 谓词将返回 false。

还要注意销毁记录 在模型中保留其 ID 例如,所以删除的模型仍然 可比。

但我的观察表明它只比较实例,而不是 id,因此以下是正确的:

a = Factory.create(:user)
b = User.find_by_email(a.email) # b is logically same as a

a.id.should == b.id # All good
a.should == b # FAILS: Contradicts the docs
a.should_not == b # Contradicts the docs
a.should_not eql b # Contradicts the docs

问题是 2 个 AR 实例被认为是不同的,而文档明确表示它们应该相等?

更新:相等性按预期工作。 上面的代码示例无关。请看下面我的回答。

【问题讨论】:

标签: ruby-on-rails ruby activerecord rspec rspec-rails


【解决方案1】:

回答我自己的问题(无关紧要)。

所有相等性检查都按预期工作(并在文档中描述)。
我认为它对我不起作用的原因是我运行 autotest 并且可能会缓存某些内容或其他一些我现在无法解释的神秘原因。

总而言之,以下所有断言确实通过了:

a = Factory.create(:user)
b = User.find_by_email(a.email) # b is logically same as a

a.id.should == b.id
a.should == b
a.should eql b
User.find_by_email(a.email).should == User.find_by_email(a.email)
a.should == User.find_by_email(a.email)
b.should == User.find_by_email(a.email)

【讨论】:

  • +1 用于提及自动测试和缓存,这解释了我在 watchr 中遇到的问题。谢谢!
【解决方案2】:

仔细查看定义:请注意,根据定义,新记录不同于任何其他记录。

在这种情况下,由于 AR 通常只对标识列进行相等性检查,因此您可以通过比较 #attributes 为每个对象返回的结果来比较两个对象。

【讨论】:

  • 2 条记录不同。但是具有相同 ID 的 2 个对象在逻辑上是相等的(根据ID .. is equal to comparison_object.id)。如果这是真的,我不明白为什么a == b 是false,因为它应该与a.id == b.id 相同(即true)。还是我错过了什么?
  • 你是对的,但这是一种特殊情况,因为变量 a 包含一条新记录,根据定义 a 将不等于任何其他记录。如果你做了 User.find(:email..)==User.find(:email..) .. 它将返回 true,因为它们不仅是相同的记录,而且它们都不是新的。
  • 没有。 a 和 b 都不是新记录。 a.new_record? 和 b.new_records? 是 false。它们只是 2 个不同的对象。与User.find(..) == User.find(..) 无关。此外,现在我的规格实际上按照文档说的那样工作,我可以使用a == b。估计是其他地方出了问题。这意味着我的问题现在已经过时并且(正如我所料)a == b 只要他们有相同的 ID 就总是正确的。
猜你喜欢
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多