[Rails] Re: Proposal for Modifications to the ActiveRecord Inheritance Model

Gleb Arshinov gleb at barsook.com
Sat Dec 11 05:57:49 GMT 2004


>>>>> "John" == John Wilger <johnwilger at gmail.com> writes:

    John> Hello, Based on recent discussions regarding the Single
    John> Table Inheritance model currenlty used by ActiveRecord, and
    John> with DHH's blessing for exploring some alternative
    John> implementations, I've posted a proposal (in PDF format)
<snip>
    John> Please look it over and reply here with any
    John> comments/suggestions.

John,

Thanks for a great writeup.  It was really helpful go get my mind
around the problem.  Here are my thoughts.

I think there are two related groups of issues here.  One group is
relational-style composition/normalization and the other one is OO
"is-a" inheritance.  I think that relational stuff is prerequisite for
OO stuff.  I'll talk about relational issues only, seeing how it is
Friday night :-)

* For relational-style composition I want to be able to store an
  object split up/normalized into multiple tables.  Aside of declaring
  the list of these tables for the class, I want Rails to take care of
  all the details of loading (including doing a join)/saving into
  multiple tables.
  
    Tables   foo [id, a, b, c, bar_id, baz_id]
             bar [id, d, e]
             baz [id, f, g]
             zip [id, i, j, bar_id]
    
    class Foo << ActiveRecord::Base
          base_table :foo
          includes_table :bar, :baz
          # has data attributes a, b, c, d, e, f, g
    end
    
    class Zip << ActiveRecord::Base
          base_table :zip
          includes_table :bar
          # has data attributes i, j, d, e
    end
  
  I don't necessarily think of bar/baz as entities, they can be just
  mixins with no real meaning of their own.  Their sole purpose is
  normalization.

* A modification of the above is when mix-ins are full blown entities,
  or at least have some behavior in addition to the data.  E.g.

    class Bar << ActiveRecord::Base
          def my_sum
              d + e
          end
    end
  
    class Zip << ActiveRecord::Base
          base_table :zip
          includes_class   :Bar
    end
  
    puts Zip.find(1).my_sum

  Including a class appears to be a more general case of including a
  table.  So, for table inclusion a reasonable implementation would
  automatically generate new classes for mix-in tables, and call on
  class inclusion to do the rest of the work.

* Efficient implementation of class inclusion seems to require
  automatic piggybacking, which would be a cool feature in itself.
  E.g.  find_all function of Zip would automatically do:

    def find_all
        ActiveRecord::Base.find_all(*params, :also_load => :Bar)
    end

  An in the same way you could do:

    Opportunity.find_first(["owner" => 23],
                           :also_load => :Account).account.address

  which will execute only 1 SQL query.

* I want to be able to include multiple children classes/mixins, with
  all the implementation consequences.

Gleb


More information about the Rails mailing list