對於has_many
< - >belongs_to
assoication,你定義一個項目是獨資(belongs_to
)由一個客戶。因此,該客戶有許多(has_many
)項目。對於確定它屬於哪個客戶端的項目,它需要有一個client_id
列,以便它可以查找它。這client_id
列使用Rails在調用client
方法,就像這樣:
Client.find(project.client_id)
這就是你如何能找到一個項目的客戶端。 client_id
列通常被稱爲外鍵,因爲它在表中不是其來源(「外來」)的唯一標識符(「鍵」)。繁榮。
當你周圍調用其他方法,找到所有的客戶端有項目,即client.projects
,Rails會的這相當於:
Project.find_all_by_client_id(client.id)
這則返回所有Project
記錄它們與特定客戶端相關,基於projects
表中的client_id
字段。
隨着has_and_belongs_to_many
協會,如用戶&組例子,你宣稱用戶has_and_belongs_to_many :groups
。現在
,如果它是一個簡單的has_many :groups
,外鍵會包含在groups
表,或者如果它是一個belongs_to
它會走在users
表。好的事情要記住:外鍵總是在具有belongs_to
的模型的表中。
您還聲明組has_and_belongs_to_many :users
,所以我們遇到了同樣的問題。我們不能在用戶表中聲明密鑰,因爲它不屬於那裏(因爲用戶有很多組,您需要存儲用戶所屬的所有組ID)或組表,原因相同。
這就是爲什麼對於has_and_belongs_to_many
我們需要創建所謂的連接表。這個表有兩個且只有兩個字段(它們都是外鍵),一個用於關聯的一側,另一個用於另一側。爲了創建這個表,我們會把這在遷移的self.up
方法:
create_table :groups_users, :id => false do |t|
t.integer :group_id
t.integer :user_id
end
幾件事情要注意這裏:
- 表名是按字母順序排列的兩個協會的兩個名字。 G出現在U之前,所以表名是
groups_users
。
- 這裏有
:id
選項,當給定值false
生成一個沒有主鍵的表。連接表不需要主鍵,因爲其目的是將其他表連接在一起。
- 我們將
group_id
和user_id
存儲爲整數字段,就像我們在belongs_to
關聯中一樣。
該表格將跟蹤哪些組具有什麼用戶,反之亦然。
不需要在users
或groups
表上定義附加列,因爲連接表已經得到了控制。
非常感謝,這非常清楚。只是一件事,Client.find(project.client_id)與project.client是一樣的,對吧?什麼client.projects?此方法是否僅由has_many語句創建? – Luc 2011-03-29 08:12:30
@Luc我已經更新了答案,就在休息時間之上。 – 2011-03-29 21:23:06