has_many through model ?

Hi,

I wonder if anyone know how I can make these relations work, I'm getting error on relationship.

Is it because I'm not doing it the rails way? Is it a MUST to have "layout_id" and "snippet_id" in the join table (container) ? Cannot I choose the column names like "reference_id" and "container_id" ?

class Layout < ActiveRecord::Base    has_many :snippets, :through => :container end

class Container < ActiveRecord::Base   belongs_to :layout, :foreign_key => :reference_id   belongs_to :snippets, :foreign_key => :container_id, :class_name => "Container::Snippet" end

class Container::Snippet < ActiveRecord::Base   has_many :layouts, :through => :container end

Thanks for help.

Regards, Jamal

Jamal Soueidan wrote:

class Layout < ActiveRecord::Base    has_many :snippets, :through => :container end

You did not supply the error, but I'm guessing you had something like:

ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :container in model Layout

This is because the "has_many :through" creates an association through another one. In your case through the "container" association which you haven't defined. You should try:

class Layout < ActiveRecord::Base   has_many :containers, :foreign_key => :reference_id   has_many :snippets, :through => :containers end

Note that the plural "containers" makes more sense here, too.

class Container::Snippet < ActiveRecord::Base   has_many :layouts, :through => :container end

The same with this model...

That helped allot Mark Bush :slight_smile: Thanks.

I just wonder why I cannot create new snippet from layout?

Layout.find(:first).snippets.create(:name => "Let me test")

NoMethodError: undefined method `layout_id=' for #<Container::Snippet:0x5cece8>

layout_id is reference_id in the container, how can I change the column name?

So I could basically just use has_and_belongs_to_many, since I thought has_many :through would be able to create new snippet through container by using...

l = Layout.find(:first) s = l.snippets.new

What do you think is the better?

Jamal Soueidan wrote:

So I could basically just use has_and_belongs_to_many, since I thought

If your join table will not be used as a model in its own right with attributes of its own, then HABTM is fine. If you want the join table to be represented by a real model with its own attributes, then you will probably start running into problems. HABTM seems to be falling out of favour, but there is no likelihood of it being dropped, I expect. Use what fits your requirements best.

Mark Bush wrote:

Jamal Soueidan wrote:

So I could basically just use has_and_belongs_to_many, since I thought

If your join table will not be used as a model in its own right with attributes of its own, then HABTM is fine. If you want the join table to be represented by a real model with its own attributes, then you will probably start running into problems. HABTM seems to be falling out of favour, but there is no likelihood of it being dropped, I expect. Use what fits your requirements best.

Thanks for explaining and thanks for help Mark :slight_smile:

I just wonder if you have the time to tell me how I can tell if the user is creating snippet, og extension?

class Container < ActiveRecord::Base   belongs_to :contents, :foreign_key => :container_id, :class_name => "Container::Content"   belongs_to :extensions, :foreign_key => :container_id, :class_name => "Container::Extension"   belongs_to :snippets, :foreign_key => :container_id, :class_name => "Container::Snippet" end

Since if the user create snippet then the "container_type" should be 'Snippet'.

PS: I have already used reference_type as simple inherit table :slight_smile:

class Join::Layout < Container   belongs_to :layout, :foreign_key => :reference_id

  private     def self.inheritance_column       'reference_type'     end end

Thanks again for your help :slight_smile:

Jamal Soueidan wrote:

I just wonder if you have the time to tell me how I can tell if the user is creating snippet, og extension?

Since if the user create snippet then the "container_type" should be 'Snippet'.

It looks like you are trying to use your join model to do inheritance. Rails can handle this for you. Look for articles on single table inheritance (STI) and polymorphic associations and see what best fits your needs.

Mark Bush wrote:

Jamal Soueidan wrote:

I just wonder if you have the time to tell me how I can tell if the user is creating snippet, og extension?

Since if the user create snippet then the "container_type" should be 'Snippet'.

It looks like you are trying to use your join model to do inheritance. Rails can handle this for you. Look for articles on single table inheritance (STI) and polymorphic associations and see what best fits your needs.

I'm already using single table inheritance on "reference_type".

It would be cool if belongs_to had before_save

belongs_to snippet, :before_create => :set_container_type

def set_container_type   container_type='Snippet' end

Don't you just want a polymorphic association ?

Fred