通过Rails了解has_one / has_many的:source选项


184

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

“指定源使用的源关联名称has_many :through => :queries。仅当无法从关联中推断出该名称时,才使用它。除非指定a,否则has_many :subscribers, :through => :subscriptions它将查找:subscribers:subscriberon 。”Subscription:source

Answers:


237

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

我认为上面的段落没有比文档中的段落清楚,因此这里是一个示例。假设我们有PetDog和三个模型Dog::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作为一个很好且方便的关联进行访问。

现在,如果现在要在上创建has_many :dog_breeds, :through => :dogs关联Pet,则突然有问题。Rails无法在上找到:dog_breeds关联Dog,因此Rails可能无法知道您要使用哪个 Dog关联。输入:source

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

使用:source,我们告诉Rails 查找:breedsDog模型上调用的关联(因为正是该模型用于:dogs),然后使用它。


2
我认为您的意思是将最后一个动物课称为“宠物课”,我相信这只是一个错字。
Kamilski81 2012年

3
在上面的示例中,下面的关联是否应该Doghas_many :breed而不是:breeds然后:source:breed单数,以代表模型名称,而不是:breeds代表表名称?例如has_many :dog_breeds, :through => :dogs, :source => :breed(不带s后缀:breed)?
LazerSharks 2014年

1
我已经测试过了 它是单数,没有s后缀:source =>
Anwar

“在这种情况下,我们选择给Dog :: Breed命名空间,因为我们想访问Dog.find(123).breeds作为一个很好的便捷关联。” 您不需要为此的名称空间吗?
Jwan622 '17

200

让我继续这个例子:

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将subscriber在Subscription类中寻找一个关联。您必须告诉它使用userSubscription类中的关联来创建订户列表。


2
请注意,单数形式的模型名称应在中使用:source =>,而不是复数形式。所以,这:users是错误的,:user是正确的
Anwar

这是最好的答案!,让我仅强调一下这一部分:“您正在将用户关联重命名为订阅者。如果不提供:source,Rails将在Subscription类中寻找一个称为订阅者的关联。”
布莱恩·约瑟夫·斯皮诺斯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.