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