Home > multi_table_inheritance

multi_table_inheritance

Multi_table_inheritance is a project mainly written in Ruby, based on the MIT license.

A Rails plugin that adds multi-table inheritance support using Postgres inheritance.

= MultiTableInheritance

A plugin that adds multi-table inheritance support to Rails using Postgres inheritance. For more information on Postgres inheritance, see http://www.postgresql.org/docs/8.3/static/ddl-inherit.html.

== Usage:

Assuming you have a base table migration like this:

class CreatePetsTable < ActiveRecord::Migration def self.up create_table :pets, :inherits_from => :profiles do |t| t.string :name, :limit => 64 t.string :species, :limit => 64 t.timestamps end end end

You can create an inherited table using the :inherits_from option.

class CreateDogsTable < ActiveRecord::Migration def self.up create_table :dogs, :inherits_from => :pets do |t| t.string :breed, :limit => 64 end

  # Executes the following in postgres:
  # CREATE TABLE dogs (
  #   "breed" character varying(64) DEFAULT NULL NULL
  # ) INHERITS (profiles)
end

end

The inherited table has all the columns of the base table in addition to any fields added in the migration. You just need to add a model for the inherited table and use the multi_table_inheritance directive.

class Dog < Pet multi_table_inheritance end

You can find inherited models through the base class, and they will be of the inherited type, just like with single-table inheritance. However, by default, when you find inherited models through the base class, all attributes added in just the inherited table will be missing. Single-table inheritance does not have this problem because all attributes exist in all classes in the hierarchy.

Pet.find(11) => #<Dog:0x19840f8 @attributes={"id"=>11, "name"=>"Daisy", "species"=>"Dog"}

Dog.find(11) => #<Dog:0x1938284 @attributes={"id"=>11, "name"=>"Daisy", "species"=>"Dog", "breed"=>"Pit/Lab Mix"}

If you would like inherited attributes to be added the inherited models when finding from the base class, use the :add_fields option.

class Dog < Pet multi_table_inheritance :add_fields => true end

Pet.find(11) => #<Dog:0x1938284 @attributes={"id"=>11, "name"=>"Daisy", "species"=>"Dog", "breed"=>"Pit/Lab Mix"}

This may have performance implications for you, because it fetches the record again from the inherited table. However, if you are using a model caching system (e.g. http://github.com/ninjudd/record_cache), the impact should be minimal.

== Install:

sudo gem install ninjudd-multi_table_inheritance -s http://gems.github.com

== Compatibility:

Requires Rails 2.3 because multi_table_inheritance overrides the default_select method in ActiveRecord::Base. Or alternatively, you can apply the following patch to construct_finder_sql in activerecord/lib/active_record/base.rb:

  • def default_select(qualified)
  • if qualified
  • quoted_table_name + '.*'
  • else
  • '*'
  • end
  • end
  •    def construct_finder_sql(options)
         scope = scope(:find)
  • sql = "SELECT #{options[:select] || (scope && scope[:select]) || (options[:joins] && quoted_table_name + '.') || ''} "
  • sql = "SELECT #{options[:select] || (scope && scope[:select]) || default_select(options[:joins] || (scope && scope[:joins]))} " sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} "

== License:

Copyright (c) 2009 Justin Balthrop, Geni.com; Published under The MIT License, see LICENSE

Previous:ms-days-2009