I’m running into a problem with the ActiveRecord::Base “==” method
defined here (it’s 2.3.2, but it looks the same in older versions
too):
# File rails-2.3.2/activerecord/lib/active_record/base.rb, line
2816
2816: def ==(comparison_object)
2817: comparison_object.equal?(self) ||
2818: (comparison_object.instance_of?(self.class) &&
2819: comparison_object.id == id &&
2820: !comparison_object.new_record?)
2821: end
Because of the last criteria (!comparison_object.new_record?),
something like this happens… say i have a new record and an existing
record (different objects) and compare them:
new == old
=> true
old == new
=> false
If this is intentional, can someone please explain why this is?
Also what is the rational of only comparing the ID and not the all the
values too and why does it matter if it’s a new record or not?
Basically the rationale is that == should mean ‘do these objects
correspond to the same database row ?’
The reason why unsaved records are special cased is that two unsaved
record would have equal id (nil in both cases) but if you saved them
you would end up with 2 distinct rows in your database.
I’m not sure why you’re getting new ==old not being the same as old
== new. They should both be false (and are on my machine)
Your case is different because of STI (so your comparisons here are
all false because the objects are of different class). If it weren’t
for that then it’s a slightly messed up situation - Active record
thinks it has a new record but it doesn’t
Your case is different because of STI (so your comparisons here are
all false because the objects are of different class). If it weren’t
for that then it’s a slightly messed up situation - Active record
thinks it has a new record but it doesn’t
Doh! Didn’t catch that. And when I do it without involving STI then
I get the results he’s getting below. Sorry Moo!
Hrm… well down in AR::Base we have this:
# Returns true if the +comparison_object+ is the same object,
or is of the same type and has the same id.
def ==(comparison_object)
comparison_object.equal?(self) ||
(comparison_object.instance_of?(self.class) &&
comparison_object.id == id &&
!comparison_object.new_record?)
end
Which interestingly enough matches each of the conditions the parent
posted about.
I guess what this means then is if you’re mucking around setting the
id’s of a record and before they are saved you should call equal?
directly.
old = AdminUser.find(1)
=> #<AdminUser id: 1…>
new = AdminUser.new
=> #
new.id = 1
=> 1
old == new
=> false
new == old
=> true
old.equal?(new)
=> false
new.equal?(old)
=> false
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.