【问题标题】:Understanding :source option of has_one/has_many through of Rails通过 Rails 理解 has_one/has_many 的 :source 选项
【发布时间】:2011-06-05 16:01:29
【问题描述】:

请帮助我理解has_one/has_many :through 关联的:source 选项。 Rails API 的解释对我来说意义不大。

"指定has_many:through => :queries使用的源关联名称。仅在无法从 协会。 has_many :subscribers, :through => :subscriptions会 在Subscription 上查找:subscribers:subscriber, 除非给出:source。 "

【问题讨论】:

    标签: ruby-on-rails-3 rails-activerecord


    【解决方案1】:

    让我扩展那个例子:

    class User
      has_many :subscriptions
      has_many :newsletters, :through => :subscriptions
    end
    
    class Newsletter
      has_many :subscriptions
      has_many :users, :through => :subscriptions
    end
    
    class Subscription
      belongs_to :newsletter
      belongs_to :user
    end
    

    使用此代码,您可以执行Newsletter.find(id).users 之类的操作来获取新闻通讯订阅者的列表。但是,如果您想更清楚并能够键入 Newsletter.find(id).subscribers,则必须将 Newsletter 类更改为:

    class Newsletter
      has_many :subscriptions
      has_many :subscribers, :through => :subscriptions, :source => :user
    end
    

    您正在将 users 关联重命名为 subscribers。如果您不提供:source,Rails 将在Subscription 类中查找名为subscriber 的关联。您必须告诉它使用 Subscription 类中的 user 关联来制作订阅者列表。

    【讨论】:

    • 请注意,单数化模型名称应在:source => 中使用,而不是复数。所以,:users 是错误的,:user 是正确的
    • 这是最好的答案!,让我强调一下这部分:“您正在将用户关联重命名为订阅者。如果您不提供 :source,Rails 将查找名为订阅者的关联在订阅类中。”
    【解决方案2】:

    有时,您希望为不同的关联使用不同的名称。如果您要用于模型上的关联名称与 :through 模型上的关联名称不同,您可以使用 :source 指定它。

    我不认为上面的段落比文档中的段落更清晰很多,所以这里有一个例子。假设我们有三个模型,PetDogDog::Breed

    class Pet < ActiveRecord::Base
      has_many :dogs
    end
    
    class Dog < ActiveRecord::Base
      belongs_to :pet
      has_many :breeds
    end
    
    class Dog::Breed < ActiveRecord::Base
      belongs_to :dog
    end
    

    在这种情况下,我们选择命名空间 Dog::Breed,因为我们希望访问 Dog.find(123).breeds 作为一个很好且方便的关联。

    现在,如果我们现在想在Pet 上创建一个has_many :dog_breeds, :through =&gt; :dogs 关联,我们突然遇到了一个问题。 Rails 将无法在Dog 上找到:dog_breeds 关联,因此Rails 不可能知道哪个您要使用Dog 关联。输入:source

    class Pet < ActiveRecord::Base
      has_many :dogs
      has_many :dog_breeds, :through => :dogs, :source => :breeds
    end
    

    使用:source,我们告诉Rails Dog 模型上寻找一个名为:breeds 的关联(因为这是用于:dogs 的模型),并使用它.

    【讨论】:

    • 我认为你的意思是你的最后一个类 Animal 被称为类 Pet,我相信只是一个错字。
    • 在上面的例子中,Dog下的关联应该是has_many :breed而不是:breeds,然后:source:breed单数,来表示模型名称,而不是:breeds代表表名?例如。 has_many :dog_breeds, :through =&gt; :dogs, :source =&gt; :breed(没有s后缀:breed)?
    • 我已经测试过了。是单数,:source =&gt;中没有s后缀
    • “在这种情况下,我们选择命名 Dog::Breed,因为我们希望访问 Dog.find(123).breeds 作为一个很好且方便的关联。”。您不需要命名空间吗?
    【解决方案3】:

    最简单的答案:

    是中间表中的关系名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-08
      • 1970-01-01
      • 1970-01-01
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多