ActiveRecord 对象相等

发布于 2024-10-22 00:34:12 字数 926 浏览 2 评论 0原文

根据 ActiveRecord::Base 的文档:

==(comparison_object) 如果comparison_object 完全相同则返回 true 对象,或 Comparison_object 属于 相同类型且自身有一个 ID,它是 等于comparison_object.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 实例被认为是不同的,而文档明确表示它们应该相等?

更新:等式确实按预期工作上面的代码示例无关。请参阅下面我的回答。

According to docs of ActiveRecord::Base:

==(comparison_object) Returns true if comparison_object is the same exact
object, or comparison_object is of the
same type and self has an ID and it is
equal to comparison_object.id.

Note that new records are different
from any other record by definition,
unless the other record is the
receiver itself. Besides, if you fetch
existing records with select and leave
the ID out, you’re on your own, this
predicate will return false.

Note also that destroying a record
preserves its ID in the model
instance, so deleted models are still
comparable.

But my observations show that it only compares instaces, not ids so that following are true:

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

The question is 2 AR instances are considered to be different while the docs explicitly say that those should be equal?

UPDATE: The equality DOES work as expected. Code sample above is irrelevant. See my answer below.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花辞树 2024-10-29 00:34:12

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

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

综上所述,以下所有断言确实通过:

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)

Answering my own question (which is irrelevant).

All the equality checks DO work as expected (and described in the docs).
I assume the reason it did not work for me is that I run autotest and something could be cached or some other mythical reason that I can't explain right now.

To summarise, all the following assertions are indeed passing:

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)
青柠芒果 2024-10-29 00:34:12

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

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

Look closer at the definition: Note that new records are different from any other record by definition.

In this case, since AR normally just does equality checks to the identity column, you can compare the two objects by comparing the result of what #attributes return for each.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文