一、使用場景
應(yīng)用單表繼承的前提條件是不同模型的字段和行為希望被共用。
比如三個模型有price、color字段,但其中有一個模型還有個width字段,這時候可以用單表繼承,存儲這三個字段,另外兩個沒有width屬性的模型,只需要將屬性設(shè)置
二、使用方法
1.首先,生成基模型 Vehicle
$ rails generate model vehicle type:string color:string price:decimal{10.2} size:integer
#生成車輛模型
“type”字段的作用是:既然所有模型都保存在這一個數(shù)據(jù)庫表中,Rails 會把保存的模型名存儲在這個type列中。對這個例子來說,“type”字段的值可能是“Car”、“Motorcycle”或“Bicycle”。
如果表中沒有“type”字段,單表繼承無法工作。
2.然后,生成三個模型,都繼承自 Vehicle
為此,可以使用 parent=PARENT 選項。這樣,生成的模型繼承指定的父模型,而且不生成對應(yīng)的遷移(因為表已經(jīng)存在)。
$ rails generate model car --parent=Vehicle #生成汽車模型,并繼承車輛模型
$ rails generate model bicycle --parent=Vehicle #生成自行車模型,并繼承車輛模型
$ rails generate model motorcycle --parent=Vehicle #生成摩托車模型,并繼承車輛模型
上述代碼生成的模型代碼為:
class Car < Vehicle
end
class Bicycle < Vehicle
end
class Motorcycle < Vehicle
end
這樣Vehicle模型中的行為在這些子模型中都可以使用,當(dāng)然也可以在子模型中重寫這些行為
3.操作數(shù)據(jù)庫
創(chuàng)建一輛汽車,相應(yīng)的記錄保存在 vehicles 表中,而且 type 字段的值是“Car”:
Car.create(color: 'Red', price: 10000, size: 100)
對應(yīng)的 SQL 如下:
INSERT INTO "vehicles" ("type", "color", "price","size") VALUES ('Car', 'Red', 10000,100)
查詢汽車記錄時只會搜索此類車輛:
Car.all
執(zhí)行的查詢?nèi)缦拢?/p>
SELECT "vehicles".* FROM "vehicles" WHERE "vehicles"."type" IN ('Car')
4.在seed檔中創(chuàng)建車輛數(shù)據(jù)
Vehicle.transaction do
Vehicle.create(type: "Car", size: 100, price: "1000",color: "red")
Vehicle.create(type: "Car", size: 200, price: "2000",color: "black") #創(chuàng)建汽車數(shù)據(jù)
Vehicle.create(type: "Bicycle", size: nil, price: "200",color: "blue") #創(chuàng)建自行車數(shù)據(jù)
end
Car.transaction do #創(chuàng)建汽車數(shù)據(jù)
Car.create(size: 120, price: "1500",color: "white")
end
Bicycle.transaction do #創(chuàng)建自行車數(shù)據(jù)
Bicycle.create(size: 80, price: "500",color: "orange")
end
三、拓展
如果我們想要讓用戶和車輛模型已經(jīng)汽車等模型建立關(guān)聯(lián)關(guān)系,則可以使用rails提供的關(guān)聯(lián)關(guān)系方法。
例如,一個用戶可以有多輛車,這些車中包含汽車。
那么就可以建立如下關(guān)聯(lián)關(guān)系:
class User < ApplicationRecord
has_many :cars, class_name: "Car", foreign_key: "user_id" #查詢用戶所有的car
has_many :vehicles, class_name: "Vehicle", foreign_key: "user_id" #查詢用戶所有的vehicle
end
class Vehicle < ApplicationRecord
belongs_to :user
end
class Car < Vehicle
belongs_to :user
end
這樣就可以使用:
User.first.cars #獲取第一個用戶的所有汽車
User.first.vehicles #獲取第一個用戶的所有車輛
Car.first.user #獲取第一輛汽車的用戶
Vehicle.first.user #獲取第一個車輛的用戶
四、案例來源
1.單表繼承--rails指南