2011-01-08 56 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

最簡單的回答:

是中間表中關係的名稱。