Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test for (ActiveRecord) object equality

In Ruby 1.9.2 on Rails 3.0.3, I'm attempting to test for object equality between two Friend (class inherits from ActiveRecord::Base) objects.

The objects are equal, but the test fails:

Failure/Error: Friend.new(name: 'Bob').should eql(Friend.new(name: 'Bob'))  expected #<Friend id: nil, event_id: nil, name: 'Bob', created_at: nil, updated_at: nil>      got #<Friend id: nil, event_id: nil, name: 'Bob', created_at: nil, updated_at: nil>  (compared using eql?) 

Just for grins, I also test for object identity, which fails as I'd expect:

Failure/Error: Friend.new(name: 'Bob').should equal(Friend.new(name: 'Bob'))  expected #<Friend:2190028040> => #<Friend id: nil, event_id: nil, name: 'Bob', created_at: nil, updated_at: nil>      got #<Friend:2190195380> => #<Friend id: nil, event_id: nil, name: 'Bob', created_at: nil, updated_at: nil>  Compared using equal?, which compares object identity, but expected and actual are not the same object. Use 'actual.should == expected' if you don't care about object identity in this example. 

Can someone explain to me why the first test for object equality fails, and how I can successfully assert those two objects are equal?

like image 623
ryonlife Avatar asked Jan 19 '11 17:01

ryonlife


People also ask

What is an ActiveRecord relation object?

The Relation Class. Having queries return an ActiveRecord::Relation object allows us to chain queries together and this Relation class is at the heart of the new query syntax. Let's take a look at this class by searching through the ActiveRecord source code for a file called relation.

What does ActiveRecord base mean?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.

Is ActiveRecord an ORM?

ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.


2 Answers

Rails deliberately delegates equality checks to the identity column. If you want to know if two AR objects contain the same stuff, compare the result of calling #attributes on both.

like image 57
noodl Avatar answered Oct 09 '22 14:10

noodl


Take a look at the API docs on the == (alias eql?) operation for ActiveRecord::Base

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.

like image 37
Andy Lindeman Avatar answered Oct 09 '22 15:10

Andy Lindeman