1.為什麼需要關聯
很多時候,比如說電子商務中的用戶和訂單,一個用戶會有很多的訂單,一個訂單只屬於一個用戶,這就是一種關聯。
在創建訂單的時候需要用戶主鍵作為外鍵,刪除用戶的的同時需要刪除用戶的訂單。
在rails中可以向下面這樣訂單關聯。
class Customer < ActiveRecord::Base has_many :orders, :dependent => :destroy end class Order < ActiveRecord::Base belongs_to :customer end
就可以像下面這樣創建訂單,刪除用戶。
@order = @customer.orders.create(:order_date => Time.now) @customer.destroy
2.關聯的類型
有下面6中關聯。
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
2.1.belongs_to
belongs_to是一種一對一的關聯。表達一種屬於的關系。
就像一個訂單只能屬於個用戶。在訂單表會有一個字段存儲用戶主鍵,這個字段是訂單表的外鍵。
class Order < ActiveRecord::Base belongs_to :customer end
2.2.has_one
has_one也是一種一對一的關聯。表達一種有一個的關系。
就像一個供應商只能有一個賬戶。賬戶表有一個供應商主鍵,是賬戶表的外鍵。
class Supplier < ActiveRecord::Base has_one :account end
2.3.has_many
has_many是一種一對多的關聯。表達有多個的關系。
就像一個用戶有多個訂單。
class Customer < ActiveRecord::Base has_many :orders end
has_many關聯的名稱需要使用復數形式。
2.4.has_many :through
has_many是一種多對多的關聯。存在一個中間的model。是通過中間model建立關聯。
有一個場景就是病人看病,但是需要和醫生進行預約。一個醫生會有多個預約記錄,一個病人也會有多個預約記錄。在預約表中會有醫生主鍵和病人主鍵。
class Physician < ActiveRecord::Base has_many :appointments has_many :patients, :through => :appointments end class Appointment < ActiveRecord::Base belongs_to :physician belongs_to :patient end class Patient < ActiveRecord::Base has_many :appointments has_many :physicians, :through => :appointments end
其實就是把醫生和病人的預約關系單獨表存放,這張表也會有主鍵。
class Document < ActiveRecord::Base has_many :sections has_many :paragraphs, :through => :sections end class Section < ActiveRecord::Base belongs_to :document has_many :paragraphs end class Paragraph < ActiveRecord::Base belongs_to :section end
2.5.has_one :through
class Supplier < ActiveRecord::Base has_one :account has_one :account_history, :through => :account end class Account < ActiveRecord::Base belongs_to :supplier has_one :account_history end class AccountHistory < ActiveRecord::Base belongs_to :account end
2.6.has_and_belongs_to_many
has_and_belongs_to_many也是一種多對多的關聯。不存在一個中間的model。關系在單獨的表中存放,但是這張表沒有單獨的id,只有雙方的id。
class Assembly < ActiveRecord::Base has_and_belongs_to_many :parts end class Part < ActiveRecord::Base has_and_belongs_to_many :assemblies end
2.7.選擇belongs_to還是has_one
belongs_to一般放在有外鍵的model中,表達一種屬於的關系。has_one表達一種擁有的關系。
class Supplier < ActiveRecord::Base has_one :account end class Account < ActiveRecord::Base belongs_to :supplier end
供應商有一個賬號,一個賬號屬於供應商。
2.8.選擇has_many :through還是has_and_belongs_to_many
如果你需要關系model作為獨立的實體,就選擇has_many :through;不需要獨立的實體就選擇has_and_belongs_to_many。
class Assembly < ActiveRecord::Base has_and_belongs_to_many :parts end class Part < ActiveRecord::Base has_and_belongs_to_many :assemblies end
class Assembly < ActiveRecord::Base has_many :manifests has_many :parts, :through => :manifests end class Manifest < ActiveRecord::Base belongs_to :assembly belongs_to :part end class Part < ActiveRecord::Base has_many :manifests has_many :assemblies, :through => :manifests end
如果在連接實體上需要驗證,回調,或者額外的屬性,那就需要使用has_many :through。
2.9.polymorphic
使用polymorphic關聯,一個model可以多個model。
就像圖片model,既屬於員工model,也屬於產品model。就是說員工和產品都有圖片,他們共享同一個圖片model。
class Picture < ActiveRecord::Base belongs_to :imageable, :polymorphic => true end class Employee < ActiveRecord::Base has_many :pictures, :as => :imageable end class Product < ActiveRecord::Base has_many :pictures, :as => :imageable end
class CreatePictures < ActiveRecord::Migration def change create_table :pictures do |t| t.string :name t.integer :imageable_id t.string :imageable_type t.timestamps end end end
class CreatePictures < ActiveRecord::Migration def change create_table :pictures do |t| t.string :name t.references :imageable, :polymorphic => true t.timestamps end end end
2.10.自連接
有時候,實體會連接自己。
就好比員工表,有些員工同時又是經理,會領導一部分的員工,這樣就會造成自連接。
class Employee < ActiveRecord::Base has_many :subordinates, :class_name => "Employee", :foreign_key => "manager_id" belongs_to :manager, :class_name => "Employee" end