views:

13

answers:

1

I have been having a problem when I try to compare two Rails models. They should evaluate as the same, but the way ActiveRecord implements == is causing it to fail. What's even stranger is the unit tests are passing.

Suppose a User has many Posts, and Posts has many Comments. User also has_many comments.

(and this is comparing two objects, which should be the same)

User.first.comments.first == Post.forst.comments.first

When I write out the object_ids to Rails.logger, they are not equal. After digging through the source code, I've found this condition makes it fail.

http://github.com/rails/rails/blob/30dcac292606da0e031d1e0dfbb6fc6109e5da60/activerecord/lib/active_record/base.rb#L1602

I expect:

User.first.comments.class.object_id == Post.first.comments.class.object_id

But this is not the case.

The model includes a module, which does the following inside self.included(base)

base.send :include, InstanceMethods
base.send :extend,  ClassMethods

When I take the include out of the models, everything works fine.

Is there something with the include/extend pattern that is causing the models to reload or not be cached correctly within the same request?

Any ideas here would be great!!!

+1  A: 

object_id is the ruby id for the instance not the id of the row in your database. The ActiveRecord override of == compares id and not object_id.

John Drummond
Hi John, it's actually the instance_of? line that is causing the failure. The objects are not equal, due to different object_ids. I am not actually comparing the object_ids in the codebase. I see that was misleading in my example, sorry about that.
releod
Also, when I put the site into production mode (ie: config.cache_classes = true), the object_ids match up, thus instance_of? passes, and all is well. This is quite confusing, and simply removing the include in the models fixes the problem. What about the include is causing the model to not cache correctly?
releod