【问题标题】:Implementing model subclasses - the correct way实现模型子类——正确的方法
【发布时间】:2013-05-18 16:18:38
【问题描述】:

我有一个 Event 模型,我想创建它的两个子类:FixedEventTasksEvent

事件模型具有以下属性:

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

FixedEvent 继承自 Event 也有这个属性:

all_day   :boolean

TasksEvent 继承自 Event 并具有以下属性:

task_id   :integer
occurrence :integer

(Occurrence 属性是任务的一种特殊表达方式:执行此任务两次/三次/x 次。出现次数表示这是该任务的哪次出现(例如,这是用户第二次执行该任务))

昨天我花了一整天的时间阅读有关单表继承和多态关联的文章,但我仍然不能 100% 确定在 Rails 中实现这一点的正确方法是什么。

单表继承在我的数据库中留下了很多空值,因为我最终会得到一个表:uid、title、starts_at、ends_at、all_day、task_id、occurrence、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 更好(或任何其他解决方案)?

【问题讨论】:

    标签: ruby-on-rails inheritance nested-forms polymorphic-associations single-table-inheritance


    【解决方案1】:

    您希望使用 STI,因为它很简单并且比加载关联要快得多。加载一堆空值没什么好担心的,性能方面。另一方面,一旦您的事件表包含数以万计的条目,连接(甚至是预加载)更有可能导致性能问题。

    如果选择所有列对您来说是个问题,您始终可以只选择所有列的子集:

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

    您似乎已经了解 STI,所以我不必在这里教您如何操作。真的很简单——只需创建带有“type”列和 Event 类的“events”表,然后对其进行子类化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多