Wrong class being returned in association

I'm using Rails 3.0.0rc and have the following models:

class User
has_many :readings
has_many :conversations, :through=>:readings
end

class Reading
belongs_to :user
belongs_to :conversation
end

class Conversation
has_many :readings
has_many :users, :through=>:readings
end

and this controller code:

class ConversationsController
def show
@user = User.find(params[:user_id])
@conversation = @user.conversations.find(params[:id])
debugger
end
end

After requesting conversations#show, go to debug console and:

User.class.object_id
=> 116350
@conversation.users.first.class.object_id
=> 33660870
@conversation.users.first.instance_of? User
=> true # Right

Then leave debugging and request the page again:
User.class.object_id
=> 116350
@conversation.users.first.class.object_id
=> 36497930
@conversation.users.first.instance_of? User
=> true # Right

And then, request the page again:
User.class.object_id
=> 116350
@conversation.users.first.class.object_id
=> 36497930
@conversation.users.first.class.to_s == User.to_s
=> true
@conversation.users.first.instance_of? User
=> false # Wrong!

This last evaluation is wrong, and breaks equality checks and
expressions such as @conversation.users.include?(some_user)

If I enable class caching, the problem disappears (but that's not
ideal for development). Maybe I'm doing something that breaks
@reflection in association_proxy.rb? Any ideas?

Sounds like you might be breaking class reloading somehow. It's
possible to do this in such a way that you have both new and old
versions of a class, which are then not equal. In the past I've found
explicit require statements (rather than require_dependency) could do
that (because require doesn't (or at least didn't) invoke the
dependency stuff at all). Models in plugins can also do this, because
typically plugins aren't reloaded, so if you have an association
between a plugin model (that doesn't get reloaded) and an application
model (which does) then weird stuff happens.

Fred

That makes a lot of sense. I'm using authlogic and acts_as_follower in
the user model. Turning them off to check which one is producing the
issue is hard, but I'll have to try. Is there a way to force plugin
classes to reload? Or, what could be the 'best practice' that is not
being followed in these plugins?

That makes a lot of sense. I'm using authlogic and acts_as_follower in
the user model. Turning them off to check which one is producing the
issue is hard, but I'll have to try. Is there a way to force plugin
classes to reload? Or, what could be the 'best practice' that is not
being followed in these plugins?

In 2.3 you can remove stuff from ActiveSupport::load_once_paths -
remove the path to the plugin's lib dir and you should be fine (I
think by the time initializers run plugins are all setup so that's
probably a good a place as any to do that)

Fred

After some research it seems that's not the cause of the problem. I
created a blank project, removed all plugins and the error persisted:

User.last.conversations.find(Conversation.last.id).users.last.instance_of?(User)

=> true

reload!

Reloading...
=> true

User.last.conversations.find(Conversation.last.id).users.last.instance_of?(User)

=> false

I removed this line I had in the Conversation model:

  default_scope :order => 'updated_at desc'

Now the models are exactly as shown in my first post, and now there's no
class bug. Of course, I have been testing with only one user, one
conversation and one reading (otherwise the order in the default scope
would make a big change in the query).