Вопрос

I have an Event model and I want to create two subclasses of it: FixedEvent and TasksEvent

Event model has these attributes:

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

FixedEvent inherits from Event and also has this attribute:

all_day   :boolean

TasksEvent inherits from Event and has these attributes:

task_id   :integer
occurrence :integer

(Occurrence attribute is a special way for tasks to say: Do this task two/three/x times. Occurrence represents which occurrence of the task this is (e.g. this is second time user is performing the task))

I spent the whole day yesterday reading about Single Table Inheritance and Polymorphic Associations and I'm still not 100% sure what's the correct way to implement this in Rails.

Single Table Inheritance leaves me with lot of null values in my database as I'll end up having one table with: uid, title, starts_at, ends_at, all_day, task_id, occurence, type. Will this behaviour make server response slower as rails will fetch more (null) data for every event query?

On the other hand, Polymorphic Associations look more like I'm adding some extra functionality to model, rather than subclassing it. Also it creates more tables (three in this case) in the db:

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

(suggest better naming for type if something comes to your mind)

fixed_events:
id
all_day
created_at
updated_at

tasks_events:
id
task_id
occurrence
created_at
updated_at

Will this behaviour make server response slower as rails will have to do several db joins every time I want to fetch all FixedEvent/TasksEvent attributes?

Also, how can I create new ActiveRecord objects using STI and/or Polymorphic Associations? I tried something like this for Polymorphic Association:

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

  respond_to :html
end

And then in 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

I had to add these two things in FixedEvent and TasksEvent and it worked:

attr_accessible :event_attributes
accepts_nested_attributes_for :event

Is this the correct way to do it or STI is better (or any other solution)?

Это было полезно?

Решение

You want to go with STI as it is simple and will be much faster than loading associations. Loading a bunch of null values is nothing to be concerned about, performance wise. On the other hand, joins (or even eager loading) is much more likely to cause performance problems once your events table contains tens of thousands of entries.

If selecting all of the columns ever becomes a problem for you, you can always just select a subset of all columns with:

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

It seems like you already understand STI so I don't have to teach you how to do it here. It's simple, really—just create the "events" table with "type" column, and Event class, then subclass it.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top