a possible bug in Has_many :through using :soucre

I’ve been stumped on this for a few days and I’m not sure if it’s an error on my end or an actual bug.
I have a system where I have workshops and users. Workshops have students, presenters, and troubleshooters. I wanted to represent this simply by using has_many :through with :source.

Workshop

has_many :presenters, :through =>:presenterships, :source=>:user

This actually works great. However, I am running into a really interesting problem when doing the assignments:

This works:

@u = User.find 1
@w = Workshop.find 1
@w.presenterships.create :user_id => [u.id](http://u.id)

But this fails:

@u = User.find 1
@w = Workshop.find 1
@w.presenterships.create :user => u

Notice t he assignment of the object instead of the id field.

The trickiest part of all this is that I get a really strange error message:

ActiveRecord::AssociationTypeMismatch: User expected, got User

    from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_recor

d/associations/association_proxy.rb:148:in raise_on_type_mismatch' from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2 /lib/active_recor d/associations/belongs_to_association.rb:22:in replace’
from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_recor
d/associations.rb:900:in user=' from c:/ruby/lib/ruby/gems/1.8/gems/activerecord- 1.15.2/lib/active_recor d/base.rb:1673:in attributes=’
from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_recor
d/base.rb:1672:in attributes=' from c:/ruby/lib/ruby/gems/1.8/gems/activerecord- 1.15.2/lib/active_recor d/base.rb:1506:in initialize_without_callbacks’
from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_recor
d/callbacks.rb:225:in initialize' from c:/ruby/lib/ruby/gems/1.8/gems/activerecord- 1.15.2/lib/active_recor d/associations/has_many_association.rb:13:in build’
from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.2/lib/active_recor
d/associations/association_collection.rb:93:in `create’

    from (irb):5

I’ve pasted my classes below. The migrations are standard (presenterships just has its own id and the two foreign keys). I’d appreciate any insight. I have a workaround but I was just wondering if this was a bug or a limitation.

class Workshop < ActiveRecord::Base

  has_many :presenterships
  has_many :presenters, :through =>:presenterships, :source=>:user

end

class Presentership < ActiveRecord::Base

  belongs_to :workshop
  belongs_to :user
end

class User
  # lots of validations
end

i tested your example exactly as you posted it and all works fine for
me using Rails 1.1.6.

w = Workshop.find 1

=> #<Workshop:0xb797928c @attributes={"name"=>"RailsConf", "id"=>"1"}>

users = User.find(:all)

=> [#<User:0xb792f650 @attributes={"name"=>"Bob", "id"=>"1"}>,
#<User:0xb792f614 @attributes={"name"=>"Joe", "id"=>"2"}>]

w.presenterships.create :user_id => users[0].id

=> #<Presentership:0xb7923828
@errors=#<ActiveRecord::Errors:0xb7922d60 @errors={},
@base=#<Presentership:0xb7923828 ...>>, @attributes={"workshop_id"=>1,
"id"=>1, "user_id"=>1}, @new_record=false>

w.presenterships.create :user => users[1]

=> #<Presentership:0xb791cd5c
@errors=#<ActiveRecord::Errors:0xb791c438 @errors={},
@base=#<Presentership:0xb791cd5c ...>>, @attributes={"workshop_id"=>1,
"id"=>2, "user_id"=>2}, @user=#<User:0xb792f614
@attributes={"name"=>"Joe", "id"=>"2"}>, @new_record=false>

w.presenters true

=> [#<User:0xb7913be4 @attributes={"name"=>"Bob", "id"=>"1"}>,
#<User:0xb79139c8 @attributes={"name"=>"Joe", "id"=>"2"}>]

Yeah… forgot to mention that I am using 1.2.1 (and now 1.2.2)
Could you confirm this?

works for 1.2.2 for me as well

RAILS_GEM_VERSION

=> "1.2.2"

w = Workshop.find :first

=> #<Workshop:0xb7629168 @attributes={"name"=>"RailsConf", "id"=>"1"}>

users = User.find(:all)

=> [#<User:0xb7620964 @attributes={"name"=>"Bob", "id"=>"1"}>,
#<User:0xb7620928 @attributes={"name"=>"Joe", "id"=>"2"}>]

w.presenterships.clear

=> []

w.presenterships.create :user_id => users[0].id

=> #<Presentership:0xb760c428
@errors=#<ActiveRecord::Errors:0xb760b898 @errors={},
@base=#<Presentership:0xb760c428 ...>>, @attributes={"workshop_id"=>1,
"id"=>5, "user_id"=>1}, @new_record=false>

w.presenterships.create :user => users[1]

=> #<Presentership:0xb76066e0
@errors=#<ActiveRecord::Errors:0xb7605da8 @errors={},
@base=#<Presentership:0xb76066e0 ...>>, @attributes={"workshop_id"=>1,
"id"=>6, "user_id"=>2}, @new_record=false, @user=#<User:0xb7620928
@attributes={"name"=>"Joe", "id"=>"2"}>>

w.presenterships

=> [#<Presentership:0xb760c428
@errors=#<ActiveRecord::Errors:0xb760b898 @errors={},
@base=#<Presentership:0xb760c428 ...>>, @attributes={"workshop_id"=>1,
"id"=>5, "user_id"=>1}, @new_record=false>, #<Presentership:0xb76066e0
@errors=#<ActiveRecord::Errors:0xb7605da8 @errors={},
@base=#<Presentership:0xb76066e0 ...>>, @attributes={"workshop_id"=>1,
"id"=>6, "user_id"=>2}, @new_record=false, @user=#<User:0xb7620928
@attributes={"name"=>"Joe", "id"=>"2"}>>]

w.presenters true

=> [#<User:0xb75ff8e0 @attributes={"name"=>"Bob", "id"=>"1"}>,
#<User:0xb75ff8b8 @attributes={"name"=>"Joe", "id"=>"2"}>]

@Chris:
Thanks for trying to duplicate. I’ve recreated this in a new project and it worked fine, so that means the current project is doing something something else that’s causing the incompatibility issue.

I was afraid it was something I did, and looks like I was right.

I don’t think it’s something you did. Check the thread titled “AssociationTypeMismatch: RoleType expected, got RoleType”

I’m having the same problem and I haven’t changed anything…only upgraded Rails. I think the reason these guys weren’t able to repeat is that it always works the first time you restart your server, but after that it’s broken. Wondering if someone has filed this as an official bug…

Jake