【问题标题】:Rails: ActiveRecord::HasManyThroughSourceAssociationNotFoundError: Could not find the source association(s)Rails:ActiveRecord::HasManyThroughSourceAssociationNotFoundError:找不到源关联
【发布时间】:2012-01-27 03:25:21
【问题描述】:

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

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

  t.timestamps
end

模型看起来像......

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

我在使用 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>'

当我添加 source =&gt; :card/:user 时,我得到了同样的结果(我相信在这种情况下应该是 :card)。

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


显示部分解决方案,因为我想清理 几样东西。迁移与以前的版本保持一致。我现在 看到在签名中找不到 user_id 的 SQL 错误(见下文)。一世 不想这么说,但大多数时候我一直在输入 :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

出现错误(减去堆栈跟踪)

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 按预期返回一个空数组。

仍在寻求这方面的帮助。在您不使用相同名称的情况下,我无法以简单、直接的解释方式找到很多内容(即您需要一个 foreign_key 和 source。

【问题讨论】:

    标签: ruby-on-rails ruby associations has-many-through


    【解决方案1】:

    好的,既然我在这方面遇到了这么大的困难,我想向大家展示一下 最终版本的样子。我过得如此艰难的很大一部分原因 解决这个问题的事实是,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
    

    Signature 类有两个belongs_to 与card 的情况是 通常会在示例中显示,并且签名者是用户类型。

    class Signature < ActiveRecord::Base
        belongs_to :card
        belongs_to :signer, :class_name => "User"
    end
    

    用户有很多签名(即使你不直接使用也是必要的) 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
    

    最后,卡片有很多签名(再次需要)和很多签名者 通过签名和signer_id的签名者的foreign_key。

    class Card < ActiveRecord::Base
        has_many :signatures
        has_many :signers, :through => :signatures, :foreign_key => 'signer_id'
    end
    

    希望这将帮助其他遇到类似问题的人。

    【讨论】:

    • 除非你调用 reload!,否则 Rails 控制台不会接收到代码的更改(即使那样它也不会接收到诸如更改 gem 或初始化程序之类的东西)
    • @FrederickCheung 谢谢!我认为它就像 Rails 本身一样,可以自动拾取东西。
    【解决方案2】:

    用户应该这样定义:

    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
    

    当您的关联名称与 :through 中使用的名称不同时,您必须定义 source 参数。如果您查看异常消息,它明确要求您这样做。

    【讨论】:

    • OK,通过该更改,我得到以下信息(减去堆栈跟踪)... 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: 没有这样的列:签名.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
    • @slabounty: has_many :signatures 需要:foreign_key =&gt; :signer_id 在那里。它期望该字段被称为user_id
    • @RyanBigg 这实际上是我的原始代码。 -- 没关系,错误的模型。让我试一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多