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

发布于 2024-12-22 12:01:29 字数 4005 浏览 0 评论 0原文

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

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 => :card 时,我得到了同样的结果/:user (我认为在这种情况下应该是:card)。

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


因为我想清理一个 几件事。迁移与之前的版本保持一致。我现在 看到 SQL 错误(见下文),在签名中找不到 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

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

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。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

中性美 2024-12-29 12:01:29

User 应如下定义:

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 参数。如果您查看异常消息,它会明确要求您执行此操作。

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.

请恋爱 2024-12-29 12:01:29

好吧,既然我在这方面遇到了很大的困难,我想向大家展示一下
最终版本看起来像。我经历如此艰难的一个重要原因
弄清楚这一点,事实是 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

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

希望这能帮助其他有类似问题的人。

OK, since I had such a hard time with this, I wanted to show everyone what the
final version looked like. A good part of the reason I had such a hard time
firguring this out, was the fact that the rails console didn't seem to be
reloading things correctly as I made changes. I didn't realize this until I
gave up one night, came back the next morning and the case that had been
working the previous night wasn't and the case that wasn't working was.

The migration is the same, but I'll repeat it for completeness sake.

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

The Signature class has the two belongs_to with card being the case that
normally gets shown in the examples and the signer being of type user.

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

The User has many signatures (necessary even if you don't use them directly)
an dmany signed_cards through signatures with a source of card (telling Rails
which class type the signed_cards are.

class User < ActiveRecord::Base
    has_many :signatures, :foreign_key => "signer_id"
    has_many :signed_cards, :through => :signatures, :source => :card 
end

Finally, the Card has many signatures (once again necessary) and many signers
through signatures and the foreign_key for the signer of signer_id.

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

Hopefully, this will help others having similar issues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文