This project is archived and is in readonly mode.
ActiveRecord::Base#== is non-commutative when comparing a loaded versus initialized object
Reported by fritz | August 31st, 2009 @ 07:02 AM
If you compare a fully loaded model object with an initialized object of the same type and with the same id, the result of the == operator depends on order of operands. For example:
>> loaded_object = MyModel.last
=> #< MyModel id: 842437485, user_id: 11, ...>
>> initialized_object = MyModel.new
=> #< MyModel id: nil, user_id: nil, ...>
>> initialized_object.id = loaded_object.id
=> 842437485
>> initialized_object == loaded_object
=> true
>> loaded_object == initialized_object # (!)
**=> false**
It's clear from the implementation why this is the case:
2811: def ==(comparison_object)
2812: comparison_object.equal?(self) ||
2813: (comparison_object.instance_of?(self.class) &&
2814: comparison_object.id == id &&
2815: ***!comparison_object.new_record?***)
2816: end
I can't imagine that the intent was a non-commutative equality operator.
This could be resolved either by ensuring that new records either never or always compare equal to records with the same id. However I'm not sure what the intent is. My instinct is "always" (i.e., removing the "&& !comparison_object.new_record?"), but I'm not totally sure of the intent.
I'm happy to submit a patch and the requisite tests if I can get some input on which way the fix should go...
Comments and changes to this ticket
-
fritz September 1st, 2009 @ 05:53 AM
Followup: we've been using the following monkeypatch locally and it seems to work well. Note the restriction on nil ids.
module ActiveRecord class Base def ==(comparison_object) comparison_object.equal?(self) || (comparison_object.instance_of?(self.class) && comparison_object.id == id && !id.nil?) end end end
-
CancelProfileIsBroken September 25th, 2009 @ 12:38 PM
- Tag changed from active_record, base, comparison, equality to active_record, base, bugmash, comparison, equality
-
Rizwan Reza January 21st, 2010 @ 07:05 AM
- Tag changed from active_record, base, bugmash, comparison, equality to active_record, base, comparison, equality
- State changed from new to resolved
This is fixed in 2-3-stable or 2.3.5.
-
csnk May 18th, 2011 @ 08:19 AM
- Importance changed from to
We are the professional shorts manufacturer, shorts supplier, shorts factory, custom shorts.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>