Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord object equality

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.

like image 908
Dmytrii Nagirniak Avatar asked Mar 16 '11 14:03

Dmytrii Nagirniak


2 Answers

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)
like image 108
Dmytrii Nagirniak Avatar answered Sep 23 '22 00:09

Dmytrii Nagirniak


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.

like image 23
Mike Lewis Avatar answered Sep 26 '22 00:09

Mike Lewis