Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s)

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.

like image 489
slabounty Avatar asked Dec 23 '11 23:12

slabounty


1 Answers

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.

like image 99
Maurício Linhares Avatar answered Oct 04 '22 03:10

Maurício Linhares