Rails:ActiveRecord :: HasManyThroughSourceAssociationNotFoundError:找不到源关联

sla*_*nty 13 ruby ruby-on-rails associations has-many-through

我有以下代码(有点简化......

create_table :signatures do |t|
  t.integer :signer_id
  t.integer :card_id

  t.timestamps
end
Run Code Online (Sandbox Code Playgroud)

随着模型看起来像......

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
Run Code Online (Sandbox Code Playgroud)

我使用rails控制台看到以下错误...

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>'
Run Code Online (Sandbox Code Playgroud)

当我添加时,我会得到同样的东西source => :card/:user(应该是:卡在这种情况下,我相信).

我在这里做错了什么想法?


显示部分解决方案,因为我想清理一些东西.迁移与以前的版本保持一致.我现在看到一个SQL错误(见下文),它在Signature中找不到user_id.我讨厌这么说,但大多数时候我一直在投入:foreign_key,不管我认为它们可能无济于事.

    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
Run Code Online (Sandbox Code Playgroud)

带错误(减去堆栈跟踪)

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
Run Code Online (Sandbox Code Playgroud)

Card.signers 按预期返回一个空数组.

还在寻找这方面的一些帮助.我没有找到很多简单,直接的解释,你没有使用相同的名称(即你需要一个foreign_key和source.

Mau*_*res 10

用户应该这样定义:

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
Run Code Online (Sandbox Code Playgroud)

当你的关联名是不是在使用的名称不同:通过你必须定义参数.如果您查看异常消息,它会明确要求您执行此操作.


sla*_*nty 6

好吧,因为我有这么艰难的时间,我想向大家展示最终版本的样子.我很难解决这个问题的一个很好的原因是,当我进行更改时,rails控制台似乎没有正确地重新加载东西.我没有意识到这一点,直到我放弃了一个晚上,第二天早上回来,前一天晚上工作的案件没有,而且那个案例没有用.

迁移是一样的,但为了完整起见,我会重复它.

def change
    create_table :signatures do |t|
        t.integer :signer_id
        t.integer :card_id
        t.boolean :signed,    :default => false
        t.text :message

        t.timestamps
    end
end
Run Code Online (Sandbox Code Playgroud)

Signature类具有两个belongs_to,其中卡通常在示例中显示,而签名者是user类型.

class Signature < ActiveRecord::Base
    belongs_to :card
    belongs_to :signer, :class_name => "User"
end
Run Code Online (Sandbox Code Playgroud)

用户有很多签名(即使你不直接使用它们也是必需的)一个带有卡片源签名的dmany signed_cards(告诉Rails类似signed_cards的类型).

class User < ActiveRecord::Base
    has_many :signatures, :foreign_key => "signer_id"
    has_many :signed_cards, :through => :signatures, :source => :card 
end
Run Code Online (Sandbox Code Playgroud)

最后,卡片有许多签名(再一次是必要的)和许多签名者通过签名和signer_id的签名者的foreign_key.

class Card < ActiveRecord::Base
    has_many :signatures
    has_many :signers, :through => :signatures, :foreign_key => 'signer_id'
end
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助其他人遇到类似的问题.