2011-01-08 58 views
138

请帮我理解has_one/has_many :through关联的:source选项。 Rails API的解释对我来说毫无意义。了解:通过Rails的has_one/has_many的源选项

“指定由has_many:through => :queries使用的源关联的名称,只有使用它,如果名称不能从 关联推断。has_many :subscribers, :through => :subscriptions将 找无论是在Subscription:subscribers:subscriber, 除非:source中给出。 “

回答

178

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

我不认为上面的段落是很多比文档中的更清晰,所以这里是一个例子。假设我们有三种型号,Pet,DogDog::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 => :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,我们告诉滑轨连接到寻找一个关联的Dog模型(因为这是用于:dogs模型)称为:breeds,并使用它。

152

让我对例如扩大:

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而必须的通讯类改成这样:

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

要重命名的users协会subscribers。如果您没有提供:source,则Rails将在Subscription类中查找名为subscriber的关联。您必须告诉它使用Subscription类中的user关联来创建订阅者列表。

+1

谢谢。更清楚的是 – Anwar 2015-09-20 18:08:32

+2

请注意,单数模型名称应该在`:source =>`中使用,而不是复数形式。所以,`:users`是错误的,`:user`是正确的 – Anwar 2015-10-18 14:04:20

5

最简单的回答:

是中间表中关系的名称。