Single table inheritence

Another question about single table inheritance.

I created PostType migration as follows:

class CreatePostTypes < ActiveRecord::Migration
def self.up
create_table :post_types do |t|

attributes for all post types

    t.column :type, :string

t.column :ptypename, :string

parent post_type_id

t.column :parent_id, :integer
end
end

def self.down
drop_table :post_types
end
end

I created PostType model as follows:

class PostType < ActiveRecord::Base
end

class MainType < PostType
end

class SubType < MainType
belongs_to :parent_type, :class_name => ‘SubType’, :foreign_key =>
:parent_id
end

when I tried doing:

MainType.new(:ptypename=>‘MAIN’) or MainType.create(:ptypename=>‘MAIN’)

I got error

NameError: uninitialized constant MainType

How can I fix it? thanks.

On 2/23/07, new rails user [email protected] wrote:

class SubType < MainType
belongs_to :parent_type, :class_name => ‘SubType’, :foreign_key =>
:parent_id
end

Ok, my initial question is: are you trying to do one level categorization
such as:

 Parent Type
        |
        |

Sub Sub

Or are you trying to do

            Parent Type
                    |
                    |
           ---------------------
        Sub                Sub
          |                      |
   -------------          --------------
 Sub       Sub     Sub        Sub

etc etc… multiple levels of types.

I am going to try do

 Parent Type
        |
        |

Sub Sub

Thanks.

Luke I. wrote:

On 2/23/07, new rails user [email protected] wrote:

class SubType < MainType
belongs_to :parent_type, :class_name => ‘SubType’, :foreign_key =>
:parent_id
end

Ok, my initial question is: are you trying to do one level categorization
such as:

 Parent Type
        |
        |

Sub Sub

Or are you trying to do

            Parent Type
                    |
                    |
           ---------------------
        Sub                Sub
          |                      |
   -------------          --------------
 Sub       Sub     Sub        Sub

etc etc… multiple levels of types.

On 2/23/07, new rails user [email protected] wrote:

Thanks.

class PostType < ActiveRecord::Base
belongs_to :parent, :class_name => ‘PostType’, foreign_key =>
‘parent_id’
has_many :sub_post_types, :class_name => ‘PostType’
end

p = PostType.new
p.save

subp = PostType.new
subp.parent = p
subp.save
subp2 = PostType.new
subp2.parent = p
subp2.save

p.sub_post_types will return [subp, subp2]
subp.parent will return p
subp2.parent will return p

And in your migration you would need

create_table :post_types do |t|
t.column :parent_id, :int
t.column :type_name, :string
end

This sets it up, actually, the second way I mentioned, but you can just
use
it as the first if you want.
Any given PostType will have a parent as post_type.parent and any given
PostType can have as many children as it wants, accessible via
post_type.sub_post_types

Is this what you need?

I tried your codes today. every thing seems ok.

sub.parent works. however it does not work after I run p.sub_post_types
and get error. The error message is

ERROR: column post_types.post_type_id does not exist
LINE 1: SELECT * FROM post_types WHERE (post_types.post_type_id = 23…
^
It seems it is looking for a column named post_type_id that does not
exist. why?

Could you please give me more hints? thanks.

Luke I. wrote:

On 2/23/07, new rails user [email protected] wrote:

This sets it up, actually, the second way I mentioned, but you can just
use
it as the first if you want.
Any given PostType will have a parent as post_type.parent and any given
PostType can have as many children as it wants, accessible via
post_type.sub_post_types

Is this what you need?

Luke I. wrote:

On 2/24/07, new rails user [email protected] wrote:

It seems it is looking for a column named post_type_id that does not
exist. why?

Could you please give me more hints? thanks.

I’m sorry, I forgot a very important part (shows what I get for not
testing
my code before I gave it to you)
The line
has_many :sub_post_types, :class_name => ‘PostType’
should instead be
has_many :sub_post_types, :class_name => ‘PostType’, :foreign_key =>
‘parent_id’

That should fix it.

This time it is working. Thanks so much.

I never though I may put :foreign_key to has_many. :wink:

On 2/24/07, new rails user [email protected] wrote:

It seems it is looking for a column named post_type_id that does not
exist. why?

Could you please give me more hints? thanks.

I’m sorry, I forgot a very important part (shows what I get for not
testing
my code before I gave it to you)
The line
has_many :sub_post_types, :class_name => ‘PostType’
should instead be
has_many :sub_post_types, :class_name => ‘PostType’, :foreign_key =>
‘parent_id’

That should fix it.

Luke I. wrote:

Yeah… what it’s doing (in case you’re curious):
When you tell the belongs_to line that it’s foreign_key is parent_id,
that
means that when you set a parent, it sets parent_id to the id of the
parent.
Then, when you call something like (p.sub_post_types), what it’s
generating
behind the scenes is SELECT * from post_types where
post_types.sub_post_type_id = #{self.id}
In order to change that query to use post_types.parent_id instead of
post_types.sub_post_type_id, you set the foreign key.

the way you do is removing type column. each time when one type looks
for its parent or sub_post_types, just use

@post_type.parent or @post_type.sub_post_types

right?

If I understand what you’re asking, then: right!

Yeah… what it’s doing (in case you’re curious):
When you tell the belongs_to line that it’s foreign_key is parent_id,
that
means that when you set a parent, it sets parent_id to the id of the
parent.
Then, when you call something like (p.sub_post_types), what it’s
generating
behind the scenes is SELECT * from post_types where
post_types.sub_post_type_id = #{self.id}
In order to change that query to use post_types.parent_id instead of
post_types.sub_post_type_id, you set the foreign key.