如何創建Rails的
STI關係,假設我們有一個模型計算機
class Computer < ActiveRecord:Base
# in app/models
# Fields:
# String name
# String owner
# String manafacturer
# String color
def default_browser
"unknown!"
end
end
現在,我們希望Mac和PC之間進行區分。爲每個表做一個不同的表是沒有意義的,因爲它們都有幾乎相同的列。相反,我們可以創建一個新的列,類型,它告訴Rails在計算機上使用STI。讓我們看看模型的外觀。
class Computer < ActiveRecord:Base
# in app/models
# Fields:
# String name
# String owner
# String manafacturer
# String color
# String type
def default_browser
"unknown!"
end
end
class Mac < Computer
# in app/models
# this is for Computers with type="Mac"
before_save :set_color
# Lets say all macs are silver, no point setting these ourselves
def set_color
self.color = "silver"
self.manafacturer = "apple"
end
# Lets overwrite the default_browser method
def default_browser
"safari"
end
end
class PC < Computer
# in app/models
# Lets overwrite the default_browser method
def default_browser
"ie =("
end
end
任何時候Rails打開計算機對象,它會查找與類型相對應的子類。例如,鍵入=「CoolComputer」對應於型號CoolComputer <計算機。
如何使用STI模式
要創建一個新的MAC,你可以這樣做:
m = Mac.new
m.name = "kunal's mac"
m.owner = "kunal"
m.save
m # => #<Mac id: 1, name: "kunal's mac", owner: "kunal", manafacturer: "apple", color: "silver", type: "Mac", ...>
請告訴我更酷的是ActiveRecord的查詢。讓我們說我們想要所有的電腦
Computer.all # => [#<Mac id: 1, name: "kunal's mac", owner: "kunal", manafacturer: "apple", color: "silver", type: "Mac", ...>, #<Mac id: 2, name: "anuj's mac", owner: "anuj", manafacturer: "apple", color: "silver", type: "Mac", ...>, #<PC id: 3, name: "bob's pc", owner: "bob", manafacturer: "toshiba", color: "blue", type: "PC", ...>]
是的,它會自動給你正確的對象!你可以通過調用.type,is_a來找出特定對象的類型。或的.class
Computer.first.type == MaC# true
Computer.first.is_a? MaC# true
Computer.first.class == MaC# true
如果我們只希望蘋果電腦,我們可以做
Mac.all
自定義繼承列
如果您想使用另一列而不是類型用於STI,您可以簡單地將此添加到您的型號頂部:
set_inheritance_column 'whatever_you want'
注意:如果您有一個名爲type的數據庫列,可以通過將繼承列更改爲非type類型來關閉Single Table Inheritance。
Rails中
組織這次使用STI之後,我結束了臃腫的模型文件夾,因爲所有的許多自定義子模型的創建我是在模型文件夾中。爲了解決這個問題,我在模型中創建的文件夾來存儲所有我的電腦的具體型號
* app
* models
* computer.rb
* computers
* pc.rb
* mac.rb
Rails沒有自動打開子文件夾中的文件夾模式,所以我的config/application.rb中加入:
# Load Subfolder Models
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{**}')]
您是否考慮將它們定義爲'events'和'句號'併爲「type_of_thing」添加一列,然後您可以調用'TimelineObject.events'或'TimelineObject.periods'或者更好的方法是使用'by_person'作用域TimelineObject .by_person(person).events' – engineersmnky