以咖啡廳來說會商品拆分成兩個 model , drink 以及 dessert
假設我們今天要開線上咖啡廳,我們可能會賣飲品以及甜點
假設我們今天有一些產品是贈品,不會有價格資訊,
一般我們會開一個欄位來存放價格資訊,
但如果贈品不需要價格,那這個欄位就蠻浪費的
Polymorphic 可以幫助我們解決這個問題
是一種無形的關聯,透過兩個欄位_id
、_type
來建立關聯
我們會透過設定告訴 Rails 哪幾個 model 是需要建立 polymorphic
目前商品有 2 個 model (如果商品有多種,可能會更多)
我們要將商品與分類來建立關聯
後面加個 {}
加上 polymorphic,表示要有 polymorphic 的欄位
rails g model Product price:integer productable:references{polymorphic}
要表示這個關聯並非普通的 belongs_to ,而是 polymorphic
多型關聯,
因此我們要在後面加上 polymorphic: true
,表示 Product 可屬於不同 model
# app/model/product.rb
class Product < ApplicationRecord
belongs_to :productable, polymorphic: true
end
要表示 Drink 與 Dessert 要作為 polymorphic 的關聯,必須加上 as: :productable
# app/model/drink.rb
class Drink < ApplicationRecord
has_one :product, as: :productable
end
# app/model/dessert.rb
class Dessert < ApplicationRecord
has_one :product, as: :productable
end
關聯性設定好之後,我們就可以來建立資料了,為了方便展示,就直接用 rails console
我們先來建立一筆飲料
# rails console
> Drink.create(name: 'oolong', description: 'Alishan oolong', capacity: 600)
因為這個品項要拿去賣,需要有價錢,
所以我需要為這個飲料新增一個 Product 的資料,並且把價格寫入
# rails console
> Product.create(price: 100, productable: Drink.last)
我們來看一下建立出來的 product 長怎樣
productable_type: 指的是跟哪個 model 有關聯
productable_id: 指的是關聯 model 中的哪筆 id
# rails console
> Drink.last.product
#<Product:0x000000010d776420
id: 3,
price: 100,
productable_type: "Drink",
productable_id: 6,
created_at: Fri, 22 Sep 2023 09:26:48.766884000 UTC +00:00,
updated_at: Fri, 22 Sep 2023 09:26:48.766884000 UTC +00:00>