1

我想在Rails中設置一個多態關係,並且遇到了一些困難。這裏是我的數據模型:has_many在Rails中的多態/繼承

class Order 
    has_many :order_items 
end 

class OrderItem 
    belongs_to :order 
end 

class PhysicalItem < OrderItem 
end 

class VirtualItem < OrderItem 
end 

PhysicalItem和VirtualItem在他們的模型足夠的差異,以保證被拆分到自己的表。所以,我設想有是:

訂單表

一個physical_items表

一個virtual_items表

一個ORDER_ITEMS表ITEM_TYPE = [ 「PhysicalItem」 或 「VirtualItem」]和ITEM_ID相應表中的匹配行。

我最終希望能夠寫出這樣的代碼:

order = Order.new 
physical_item = PhysicalItem.new 
virtual_item = VirtualItem.new 

order.order_items << physical_item 
order.order_items << virtual_item 

puts order.order_items 
# Should list out the physical item and then the virtual item. 

似乎在理論上很簡單,但它看起來並不像有這種結構一般很大的支持。任何人有任何關於在ActiveRecord postgresql數據庫中實現這個想法?

+0

當'PhysicalItem'和'VirtualItem'繼承產品時,我在列表中看不到產品模型?它在哪裏適合所有這些? – jvperrin

+0

我想我並不真的需要產品模型 - 我唯一能從中得到的是查詢order.products,然後檢索一堆混合的PhysicalItems和VirtualItems。 –

+0

另外,我編輯了我的問題,以反映我更新的對象名稱 - 對於之前的混淆抱歉。 –

回答

1

你不應該爲此需要多態關聯。在Order模型的方法將工作一樣好:

class Order < ActiveRecord::Base 
    has_many :physical_items 
    has_many :virtual_items 

    def order_items 
    physical_items + virtual_items 
    end 
end 

class PhysicalItem < ActiveRecord::Base 
    belongs_to :order 
end 

class VirtualItem < ActiveRecord::Base 
    belongs_to :order 
end 

您還需要physical_itemsvirtual_items表,都有order_id列。然後,要複製您想要的行爲:

order = Order.new 
physical_item = order.physical_items.new 
virtual_item = order.virtual_items.new 

puts order.order_items 
+0

當然,但讓我們假設有人向他們的購物車中添加了30種不同的物品。我想選擇他們添加的前10個項目 - 我不能在不查詢所有項目的情況下,通過created_at時間戳對最終列表進行排序,然後丟棄其他模型。這將是一個非常緩慢的操作。 –

0

您可以將PostgreSQL HStore數據類型與STI結合使用。通過這種方式,您可以獲得在一個表上運行單個SELECT的好處,但該表不會受到類型特定列的污染。

這樣您就可以只有兩個表:

  • 訂單表
  • ORDER_ITEMS表

對於ORDER_ITEMS表遷移將包括:

class CreateOrderItemsTable < ActiveRecord::Migration 
    def change 
    create_table :order_items do |t| 
     t.integer :order_id 
     t.string :type 
     t.hstore :data 
    end 
    end 
end 

你的模型會看起來像這樣:

class Order 
    has_many :order_items 
end 

class OrderItem 
    belongs_to :order 
    serialize :data, ActiveRecord::Coders::Hstore 
end 

class PhysicalItem < OrderItem 
end 

class VirtualItem < OrderItem 
end 

我試過使用多態連接表,但它仍然需要太多的SQL quires來獲取關聯列表。 HSTORE與STI是一個很好的組合。欲瞭解更多信息,請閱讀:http://www.devmynd.com/blog/2013-3-single-table-inheritance-hstore-lovely-combination