guh.me - gustavo's personal blog

Easy multiple table inheritance in Rails 3

βΈ»

I needed to setup multiple table inheritance in Rails, but I could not find a good solution for it. Single table inheritance was not a good a option, but I managed to find some gems that promised (they lied! lol) to abstract this relation.

I found a gem called Heritage (https://github.com/BenjaminMedia/Heritage) that did work well, even though it had some bugs (related to mass assignment). After inspecting its source code, I came up with my own solution using a mixin.

Herein lies the code I came up with. It met my needs, and yes, it could should be improved to include transaction control and to be reusable.

module Statusable
  module Heir
    # Fetches predecessor object
    def predecessor
      Status.find_by_heir_id(id)
    end

    # Adds validation and accessor methods
    def self.included(base)
      attr_accessor :user_id
      base.validates :user_id, presence: true
      base.after_create :create_status
    end

    private
    # Creates a new status after persisting heir
    def create_status
      s = Status.new
      s.user_id   = user_id
      s.heir_type = self.class.name
      s.heir_id   = id
      s.save
    end
  end

  module Predecessor
    # Fetches heir object
    def heir
      heir_type.constantize.find(heir_id)
    end
  end
end
class Status < ActiveRecord::Base
  # Includes statusable behavior (for multiple inheritance)
  include Statusable::Predecessor

  # Relations
  has_many :status_comments
  has_many :status_likes
  belongs_to :user

  # Callbacks

  # Validations
  validates :user_id, presence: true
end
class StatusUpdate < ActiveRecord::Base
  # Includes statusable behavior (for multiple inheritance)
  include Statusable::Heir

  # Multiple table inheritance
  attr_accessible :content

  # Validations
  validates :content, presence: true
end