多型關聯


如果有Some、Other兩個物件,若說Some擁有一個Other,可以如下定義:

class Some < ActiveRecord::Base
    has_one :other
end

則此時others表格中要有個some_id欄位作為外部鍵,參考至somes表格中的id主鍵。類似地,如果Some擁有多個Other,可以如下定義:

class Some < ActiveRecord::Base
    has_many :others
end

則此時others表格中要有個some_id欄位作為外部鍵,參考至somes表格中的id主鍵。

如果希望Other被Some與Another共用,例如在一對一的情況:

class Some < ActiveRecord::Base
    has_many :others
end

class Another < ActiveRecord::Base
    has_many :others
end

那麼此時others表格中必須要有some_id與another_id,分別參考至somes表格與anothers表格的id,如果Other要被更多模型共用,更會形成欄位的浪費。

此時可以透過多型關聯方式,例如:

class Some < ActiveRecord::Base
    has_many :others, :as => :owner # 我有許多other,而other會把我看成是owner
end

class Another < ActiveRecord::Base
    has_many :others, :as => :owner    # 我有許多other,而other會把我看成是owner
end

class Other < ActiveRecord::Base
    belongs_to :owner, :polymorphic => true # 我屬於owner
end

如上指定之後,others中要有owner_id與owner_type兩個欄位,依照owner_type可得知owner_id是參考到somes或anothers的id,表格關係如下所示:

PolymorphicAssociations

對於Some或Other實例而言,依舊是使用others方法取得關聯的資料。

others表格的建立上,可以如下:

class CreateOthers < ActiveRecord::Migration
  def change
    create_table :others do |t|
      t.string  :name
      t.integer :owner_id
      t.string  :owner_type
      t.timestamps
    end
  end
end


也可簡化為:

class CreateOthers < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.string :name
      t.references :owner, :polymorphic => true
      t.timestamps
    end
  end
end

一個具體的例子可在 A Guide to Active Record Associations2.9 Polymorphic Associations 看到,將Picture作為Employee與Product共用的模型:

2.9 Polymorphic Associations