Active Record Inheritence

Discussion in 'Ruby' started by Andrew Libby, Oct 14, 2006.

  1. Andrew Libby

    Andrew Libby Guest

    Greetings,

    I'm having some troubles getting single table inheritance
    working. I'm outside of rails, and I _think_ I understand
    the way this whole thing is supposed to work. I've got
    tables in a PostgreSQL database, (principal and user, the
    User class extends Principal).

    When I run the following code I get an error like so:

    /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:1789:in
    `method_missing': undefined method `first_name=' for
    #<User:0xb7d815cc @attributes={"type"=>"User"},
    @new_record=true> (NoMethodError)

    When I change the class definition of User to extend
    ActiveRecord::Base the code works and I wind up with rows in
    the users table.

    Any ideas what I'm not doing correctly?


    The code:

    #!/usr/bin/ruby


    #CREATE TABLE principals (
    # id integer DEFAULT nextval('id_seq'::text) NOT NULL,
    # "type" text
    #);
    #
    #
    #CREATE TABLE users (
    # id integer DEFAULT nextval('id_seq'::text) NOT NULL,
    # username text,
    # "password" text,
    # first_name text,
    # last_name text
    #);

    require 'rubygems'
    require 'active_record'

    ActiveRecord::Base.establish_connection(
    :adapter => "postgresql",
    :host => "localhost",
    :username => "org",
    :password => "xx",
    :database => "org"
    )

    class Principal < ActiveRecord::Base

    end

    class User < Principal

    end

    u = User.new
    u.first_name = 'joejoe'

    --
    Andrew Libby
    Tangeis, LLC
    Innovative IT Management Solutions
    Andrew Libby, Oct 14, 2006
    #1
    1. Advertising

  2. Andrew Libby

    Guest

    Hi --

    On Sun, 15 Oct 2006, Andrew Libby wrote:

    >
    > Greetings,
    >
    > I'm having some troubles getting single table inheritance working. I'm
    > outside of rails, and I _think_ I understand the way this whole thing is
    > supposed to work. I've got tables in a PostgreSQL database, (principal and
    > user, the User class extends Principal).
    >
    > When I run the following code I get an error like so:
    >
    > /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/base.rb:1789:in
    > `method_missing': undefined method `first_name=' for #<User:0xb7d815cc
    > @attributes={"type"=>"User"}, @new_record=true> (NoMethodError)
    >
    > When I change the class definition of User to extend ActiveRecord::Base the
    > code works and I wind up with rows in the users table.
    >
    > Any ideas what I'm not doing correctly?
    >
    >
    > The code:
    >
    > #!/usr/bin/ruby
    >
    >
    > #CREATE TABLE principals (
    > # id integer DEFAULT nextval('id_seq'::text) NOT NULL,
    > # "type" text
    > #);
    > #
    > #
    > #CREATE TABLE users (
    > # id integer DEFAULT nextval('id_seq'::text) NOT NULL,
    > # username text,
    > # "password" text,
    > # first_name text,
    > # last_name text
    > #);
    >
    > require 'rubygems'
    > require 'active_record'
    >
    > ActiveRecord::Base.establish_connection(
    > :adapter => "postgresql",
    > :host => "localhost",
    > :username => "org",
    > :password => "xx",
    > :database => "org"
    > )
    >
    > class Principal < ActiveRecord::Base
    >
    > end
    >
    > class User < Principal
    >
    > end
    >
    > u = User.new
    > u.first_name = 'joejoe'


    If you want to do single table inheritance, you need to use a single
    table :) You're using two (principals and users).

    Try the following:

    1. add a type/text column to users
    2. get rid of principals
    3. in the models, do:

    class User < ActiveRecord::Base
    end

    class Principal < User
    end

    I know I've reversed the inheritance flow; it seems to make more sense
    this way, but you can of course switch it around.


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
    , Oct 14, 2006
    #2
    1. Advertising

  3. Andrew Libby

    Andrew Libby Guest

    wrote:
    > Hi --
    >
    >
    > If you want to do single table inheritance, you need to use a single
    > table :) You're using two (principals and users).
    >
    > Try the following:
    >
    > 1. add a type/text column to users
    > 2. get rid of principals
    > 3. in the models, do:
    >
    > class User < ActiveRecord::Base
    > end
    >
    > class Principal < User
    > end
    >
    > I know I've reversed the inheritance flow; it seems to make more sense
    > this way, but you can of course switch it around.
    >
    >
    > David
    >



    Thanks for your comments. It seems I completely missed
    what single table inheritance is all about. You'd thing by
    calling it single table, I'd have gotten that it was
    _single_table_.. I'm hoping to have other principal types
    in my system (groups, systems, users, etc). I guess I'll
    need to work something out with
    has_a, am I pointing in the right direction?

    Thanks.

    Andy


    --
    Andrew Libby
    Tangeis, LLC
    Innovative IT Management Solutions
    Andrew Libby, Oct 14, 2006
    #3
  4. Andrew Libby

    Guest

    Hi --

    On Sun, 15 Oct 2006, Andrew Libby wrote:

    >
    >
    >
    > wrote:
    >> Hi --
    >>
    >>
    >> If you want to do single table inheritance, you need to use a single
    >> table :) You're using two (principals and users).
    >>
    >> Try the following:
    >>
    >> 1. add a type/text column to users
    >> 2. get rid of principals
    >> 3. in the models, do:
    >>
    >> class User < ActiveRecord::Base
    >> end
    >>
    >> class Principal < User
    >> end
    >>
    >> I know I've reversed the inheritance flow; it seems to make more sense
    >> this way, but you can of course switch it around.
    >>
    >>
    >> David
    >>

    >
    >
    > Thanks for your comments. It seems I completely missed
    > what single table inheritance is all about. You'd thing by calling it single
    > table, I'd have gotten that it was _single_table_.. I'm hoping to have other
    > principal types in my system (groups, systems, users, etc). I guess I'll
    > need to work something out with
    > has_a, am I pointing in the right direction?


    The has_one stuff is separate from the STI stuff. The basic idea of
    STI is that you have one table (principals [switching my example back
    to the way yours was]) that has columns for *all* of the attributes
    that *any* of the descendants might have. In other words, the single
    table is a flattened, centralized collection. This is, in a sense,
    illogical. It means that if you have, say, a people table, and then
    subclasses of Person like Employee and Customer, technically Customers
    will have all of the same characteristics as Employees -- including,
    perhaps, salary. The point though is that in exchange for a bit of
    weirdness in the database table, you receive a lot of ease at the Ruby
    end, where you can accomplish a lot just through inheritance.

    In the case you're describing, if principals is the single table, it
    would have to include all the future fields for groups, systems, and
    users. That makes me wonder whether STI is actually a good fit for
    this case. You should only use STI when the descendant classes are
    pretty similar, and only diverge in a small number of fields. It
    sounds like a system and a user would be very different from each
    other.

    The associations (has_one/belongs_to, etc.) might make more sense
    here. A User could belong_to a group; Group would have many users;
    and so forth.


    David

    --
    David A. Black |
    Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
    DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
    [1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
    [2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
    , Oct 14, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?SnVzdGlu?=

    Retrieving Record Key while creating the record.

    =?Utf-8?B?SnVzdGlu?=, Oct 4, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    611
    =?Utf-8?B?SnVzdGlu?=
    Oct 5, 2004
  2. darrel

    Handling DB record inheritence?

    darrel, Dec 22, 2005, in forum: ASP .Net
    Replies:
    0
    Views:
    328
    darrel
    Dec 22, 2005
  3. André
    Replies:
    0
    Views:
    3,725
    André
    Jun 25, 2006
  4. MRW
    Replies:
    0
    Views:
    361
  5. THurkmans
    Replies:
    2
    Views:
    582
Loading...

Share This Page