1

我有一個Event模型,我想創建它的兩個子類:FixedEventTasksEvent實現模型子類 - 的正確方法

事件模型具有以下屬性:

uid  :string 
title  :string 
starts_at :datetime 
ends_at :datetime 

FixedEvent從事件和繼承也有這樣的屬性:

all_day :boolean 

TasksEvent從事件繼承,並具有以下屬性:

task_id :integer 
occurrence :integer 

(發生屬性是任務說的特殊方式:執行此任務兩次/三次/ x次。出現表示這是任務的其中發生(例如,這是第二次用戶正在執行的任務))

我昨天花了一整天唸叨單表繼承和多態關聯,我還沒有100%地肯定什麼在Rails中實現這一點的正確方法。

Single Table Inheritance在我的數據庫中留下了很多空值,因爲我最終會得到一個帶有:uid,title,starts_at,ends_at,all_day,task_id,occurence,type的表。 此行爲會使服務器響應變慢嗎,因爲rails會爲每個事件查詢獲取更多(空)數據?

另一方面,多態關聯看起來更像是我爲模型添加了一些額外的功能,而不是對它進行子類化。此外,它會在數據庫多個表(三家在這種情況下):

events: 
id, uid, title, starts_at, ends_at, 
created_at, updated_at, 
event_type_id, event_type_type 

(建議爲類型更好的命名,如果事情涉及到你的頭腦)

fixed_events: 
id 
all_day 
created_at 
updated_at 

tasks_events: 
id 
task_id 
occurrence 
created_at 
updated_at 

將這種行爲使服務器響應慢如每次我想要獲取所有FixedEvent/TasksEvent屬性時,rails都必須執行多個數據庫連接?

另外,如何使用STI和/或多形關聯創建新的ActiveRecord對象? 我想是這樣的多態協會:

def new 
    @fixed_event = FixedEvent.new 
    @fixed_event.build_event 

    respond_to :html 
end 

然後在的form_for:

= f.fields_for :event do |event| 
    .field 
    = event.label :title 
    = event.text_field :title 
    .field 
    = event.label :starts_at 
    = event.datetime_select :starts_at 
    .field 
    = event.label :ends_at 
    = event.datetime_select :ends_at 
    .field 
    = event.label :description 
    = event.text_field :description 
    .field 
    = event.label :uid 
    = event.text_field :uid 

我不得不在FixedEventTasksEvent添加這兩樣東西,它的工作:

attr_accessible :event_attributes 
accepts_nested_attributes_for :event 

這是做這件事的正確方法還是STI更好(或其他解決方案)?

回答

1

你想和STI一起去,因爲它很簡單,並且比加載關聯要快得多。加載一堆空值不值得關注,性能明智。另一方面,一旦事件表包含數以萬計的條目,連接(或甚至是急切的加載)更可能導致性能問題。

如果選擇所有的列曾經成爲你一個問題,你永遠可以選擇所有列的一個子集:

FixedEvent.select('foo, bar').all 

好像你已經明白STI,所以我不必教你如何在這裏做。這很簡單,實際上只需用「type」列和Event類創建「events」表,然後對其進行子類化。