Search code examples
ruby-on-railssingle-table-inheritance

How to structure this so I get all the benefits from STI with none of the consequences? (Pretty irresponsible, I know.)


Say I have the following example of associations in a Rails app:

enter image description here

I'm considering combining the *Posting models under STI. One problem with STI is the potential for many attributes that are only related to one subclass (i.e., a lot of denormalized nil values). This is especially worrisome when your subclasses and going to evolve and grow in the future. I've read a few related posts (such as this), however, as you can see in my example, the potential subclass-specific fields will not necessarily be just attributes, but rather, a lot of belongs_to associations.

My question is, how could I restructure this to use STI from a Posting model for all the common attributes/methods (of which there will be quite a few in my actual app), but keep the unique subclass-specific attributes and belongs_to associations from piling up in the Posting model? Also, the ability to access @board.postings and work with those standard methods is important.

For example, I've thought about moving the type-specific attributes to another model:

class CarPosting < Posting
  has_one: car_posting_detail
end

class CarPostingDetail < ActiveRecord::Base
  belongs_to :car_posting
  belongs_to :car_make
  belongs_to :car_model
end

Although, this starts to create a lot of joins, I'm not sure I have the has_one/belongs_to declarations in the right direction, and you have to start chaining calls (e.g., @posting.car_posting_detail.car_make).

Are there other design patterns you have seen for accomplishing this?


Solution

  • You could use polymorphic associations for this.

    Post model belongs_to :postable, :polymorphic => true
    

    car, event and all the other "postable" classes would have this relationship

    has_many :posts, as: :postable 
    

    Post would hold the postable_id and postable_type

    More info here http://guides.rubyonrails.org/association_basics.html#polymorphic-associations