Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I has_and_belongs_to_many multiple instances of the same model?

Basically, I want to accomplish something like this:

Class Node < ActiveRecord::Base
  has_and_belongs_to_many :parents, :class_name=>'Node'
  has_and_belongs_to_many :children, :class_name=>'Node'
end

but it isn't working, and I'm not entirely sure the proper way to do this. I'm going to try explicitly defining a join table next and have both use it: If that's the solution, would the column be called "children_id" or "child_id"?

like image 208
GlyphGryph Avatar asked Nov 30 '22 15:11

GlyphGryph


2 Answers

Class Node < ActiveRecord::Base
  has_and_belongs_to_many :parents, :class_name=>'Node', :join_table => "parents_children", :foreign_key => :child_id, :association_foreign_key => :parent_id
  has_and_belongs_to_many :children, :class_name=>'Node', :join_table => "parents_children", :foreign_key => :parent_id, :association_foreign_key => :child_id
end

Note that you can rename the join table and foreign keys as long as you set the appropriate foreign key names here.

like image 137
PinnyM Avatar answered Dec 02 '22 04:12

PinnyM


This is doable, but I strongly recommend using has_many :through instead:

class Node < ActiveRecord::Base
  has_many :parent_node_links,
    :class_name => 'NodeLink',
    :foreign_key => :child_id

  has_many :parents,
    :through => :parent_node_links,
    :source => :parent

  has_many :child_node_links,
    :class_name => 'NodeLink',
    :foreign_key => :parent_id

  has_many :children,
    :through => :child_node_links,
    :source => :child
end

class NodeLink < ActiveRecord::Base
  belongs_to :parent,
    :class_name => "Node"
  belongs_to :child,
    :class_name => "Node"
end

Having a first-class join model makes it much easier to manage the relationships and gives you the freedom to add relevant meta-data at a later point in time.

like image 37
tadman Avatar answered Dec 02 '22 05:12

tadman