I have the following code (somewhat simplified ...
create_table :signatures do |t|
t.integer :signer_id
t.integer :card_id
t.timestamps
end
With the models looking like ...
class Signature < ActiveRecord::Base
belongs_to :card
belongs_to :user
end
class Card < ActiveRecord::Base
has_many :signatures
has_many :signers, :through => :signatures, :foreign_key => "card_id"
end
class User < ActiveRecord::Base
has_many :sent_cards, :class_name => "Card", :foreign_key => "sender_id"
has_many :received_cards, :class_name => "Card", :foreign_key => "recipient_id"
has_many :signatures
has_many :signed_cards, :through => :signatures, :foreign_key => "signer_id"
end
I see the following error using the rails console ...
ruby-1.9.2-p0 > u15.signed_cards
ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s) :signed_card or :signed_cards in model Signature. Try 'has_many :signed_cards, :through => :signatures, :source => <name>'. Is it one of :card or :user?
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/reflection.rb:517:in `check_validity!'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/associations/association.rb:27:in `initialize'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/associations/collection_association.rb:24:in `initialize'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/associations.rb:164:in `new'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/associations.rb:164:in `association'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/activerecord-3.1.0/lib/active_record/associations/builder/association.rb:41:in `block in define_readers'
from (irb):11
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.1.0/lib/rails/commands/console.rb:45:in `start'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.1.0/lib/rails/commands/console.rb:8:in `start'
from /home/slabounty/.rvm/gems/ruby-1.9.2-p0/gems/railties-3.1.0/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I get the same thing when I do add the source => :card/:user
(should be :card in this case I believe).
Any ideas what I'm doing wrong here?
Showing a partial solution because I wanted to clean up a few things. The migration remained the same as the previous version. I'm now seeing a SQL error (see below) where it can't find user_id in Signature. I hate to say it, but mostly I've been putting in :foreign_key whereever I think they might help to no avail.
class Signature < ActiveRecord::Base
belongs_to :card
belongs_to :signer, :class_name => "User"
end
class Card < ActiveRecord::Base
# Correct
has_many :signatures
has_many :signers, :through => :signatures, :source => :user
end
class User < ActiveRecord::Base
# Wrong!
has_many :signatures, :foreign_key => "signer_id"
has_many :signed_cards, :through => :signatures, :source => :card
end
With the error (minus stack trace)
ruby-1.9.2-p0 > u15.signed_cards
Card Load (0.5ms) SELECT "cards".* FROM "cards" INNER JOIN "signatures" ON "cards"."id" = "signatures"."card_id" WHERE "signatures"."user_id" = 15 ORDER BY cards.created_at DESC
SQLite3::SQLException: no such column: signatures.user_id: SELECT "cards".* FROM "cards" INNER JOIN "signatures" ON "cards"."id" = "signatures"."card_id" WHERE "signatures"."user_id" = 15 ORDER BY cards.created_at DESC
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: signatures.user_id: SELECT "cards".* FROM "cards" INNER JOIN "signatures" ON "cards"."id" = "signatures"."card_id" WHERE "signatures"."user_id" = 15 ORDER BY cards.created_at DESC
Card.signers
returns an empty array as expected.
Still looking for some help on this one. I haven't been able to locate much in the way of simple, straightforward explanations of this where you're not using the same names (i.e. you need a foreign_key and source.
User should be defined like this:
class User < ActiveRecord::Base
has_many :sent_cards, :class_name => "Card", :foreign_key => "sender_id"
has_many :received_cards, :class_name => "Card", :foreign_key => "recipient_id"
has_many :signatures
has_many :signed_cards, :through => :signatures, :source => :card
end
When your association name is different than the name used at the :through you have to define the source parameter. If you look at the exception message it explicitly asks you to do it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With