Edoardo "Dado" Marcora
2006-Mar-15 03:10 UTC
[Rails] Self-referential join model does not work
I have been trying to model a labeled graph using ActiveRecord (trunk
version). Basically, I have a ''Node'' model which represents a
node linking
to other nodes. Links (aka edges) are labeled (i.e., have a
''label''
attribute and other behavior). Thus I decided to model edges as an
''Edge''
model and use a ''has_many :trough'' association in the Node
model. However,
it just doesn''t work, regardless of how hard I''ve tried.
The database structure is as follows:
class InitialSchema < ActiveRecord::Migration
def self.up
create_table :nodes do |t|
t.column :title, :string, :null => false
t.column :body, :text, :null => false, :default =>
''''
end
create_table :edges do |t|
t.column :node_id, :integer, :null => false
t.column :related_node_id, :integer, :null => false
t.column :label, :string, :null => false, :default =>
''''
end
add_index :edges, [:node_id, :related_node_id], :unique => true
end
def self.down
drop_table :edges
drop_table :nodes
end
end
The two models are as follows:
class Node < ActiveRecord::Base
validates_presence_of :title
has_many :edges, :dependent => true
has_many :related_nodes, :through => :edges, :class_name =>
''Node'', :foreign_key => ''node_id''
end
class Edge < ActiveRecord::Base
belongs_to :node
belongs_to :related_node, :class_name => ''Node'',
:foreign_key =>
''related_node_id''
validates_uniqueness_of :related_node_id, :scope => :node_id
validates_presence_of :node, :related_node
end
In script/console I then create two nodes and link them with an edge as
follows:
>> from_node = Node.create :title => ''From''
>> to_node = Node.create :title => ''To''
>> e = Edge.create :node => from_node, :related_node => to_node
>> from_node.edges.find_first.related_node
=> #<Node:0xb7430ee4 @attributes={"body"=>"",
"title"=>"To", "id"=>"2"}>
SO FAR SO GOOD! but if I ask the ''from_node'' for
''related_nodes'' this is
what I get back!!!
>> from_node.edges.related_nodes.find_first
=> #<Node:0xb742e20c @attributes={"body"=>"",
"title"=>"From", "id"=>"1"}>
Same result even if I change :foreign_key in the Node model from
''node_id''
to ''related_node_id''. Furthermore, :association_foreign_key is
not accepted
as a parameter to has_many :through associations.
Does anybody have a clue of what I am doing wrong here? Or is it that Rails
1.1 does not support self-referential join models?
Thanx in advance for the help and consideration,
Edoardo "Dado" Marcora
See if the patch at http://dev.rubyonrails.org/ticket/4289 works for you. It adds the :association_foreign_key to has_many. On 3/14/06, Edoardo Dado Marcora <marcora@caltech.edu> wrote:> I have been trying to model a labeled graph using ActiveRecord (trunk > version). Basically, I have a ''Node'' model which represents a node linking > to other nodes. Links (aka edges) are labeled (i.e., have a ''label'' > attribute and other behavior). Thus I decided to model edges as an ''Edge'' > model and use a ''has_many :trough'' association in the Node model. However, > it just doesn''t work, regardless of how hard I''ve tried. > > The database structure is as follows: > > class InitialSchema < ActiveRecord::Migration > def self.up > create_table :nodes do |t| > t.column :title, :string, :null => false > t.column :body, :text, :null => false, :default => '''' > end > create_table :edges do |t| > t.column :node_id, :integer, :null => false > t.column :related_node_id, :integer, :null => false > t.column :label, :string, :null => false, :default => '''' > end > add_index :edges, [:node_id, :related_node_id], :unique => true > end > def self.down > drop_table :edges > drop_table :nodes > end > end > > The two models are as follows: > > class Node < ActiveRecord::Base > validates_presence_of :title > has_many :edges, :dependent => true > has_many :related_nodes, :through => :edges, :class_name => > ''Node'', :foreign_key => ''node_id'' > end > > class Edge < ActiveRecord::Base > belongs_to :node > belongs_to :related_node, :class_name => ''Node'', :foreign_key => > ''related_node_id'' > validates_uniqueness_of :related_node_id, :scope => :node_id > validates_presence_of :node, :related_node > end > > In script/console I then create two nodes and link them with an edge as > follows: > > >> from_node = Node.create :title => ''From'' > >> to_node = Node.create :title => ''To'' > >> e = Edge.create :node => from_node, :related_node => to_node > >> from_node.edges.find_first.related_node > => #<Node:0xb7430ee4 @attributes={"body"=>"", "title"=>"To", "id"=>"2"}> > > SO FAR SO GOOD! but if I ask the ''from_node'' for ''related_nodes'' this is > what I get back!!! > > >> from_node.edges.related_nodes.find_first > => #<Node:0xb742e20c @attributes={"body"=>"", "title"=>"From", "id"=>"1"}> > > Same result even if I change :foreign_key in the Node model from ''node_id'' > to ''related_node_id''. Furthermore, :association_foreign_key is not accepted > as a parameter to has_many :through associations. > > Does anybody have a clue of what I am doing wrong here? Or is it that Rails > 1.1 does not support self-referential join models? > > Thanx in advance for the help and consideration, > > Edoardo "Dado" Marcora > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Edoardo Dado Marcora
2006-Mar-20 05:18 UTC
[Rails] Re: Self-referential join model does not work
Thanx for adding the ticket and for coming up with the patch. I am sure things will be resolved quickly in rails/trunk. Lee Marlow wrote:> See if the patch at http://dev.rubyonrails.org/ticket/4289 works for > you. It adds the :association_foreign_key to has_many.-- Posted via http://www.ruby-forum.com/.
Did you get this sorted? I got something that works for me using the lovely :through. I copied it onto a blogger account since it would have been real messy here.... http://rubbishshoes.blogspot.com/2006/03/self-referential-many-many-using.html beers -h On 3/15/06, Edoardo Dado Marcora <marcora@caltech.edu> wrote:> I have been trying to model a labeled graph using ActiveRecord (trunk > version). Basically, I have a ''Node'' model which represents a node linking > to other nodes. Links (aka edges) are labeled (i.e., have a ''label'' > attribute and other behavior). Thus I decided to model edges as an ''Edge'' > model and use a ''has_many :trough'' association in the Node model. However, > it just doesn''t work, regardless of how hard I''ve tried. > > The database structure is as follows: > > class InitialSchema < ActiveRecord::Migration > def self.up > create_table :nodes do |t| > t.column :title, :string, :null => false > t.column :body, :text, :null => false, :default => '''' > end > create_table :edges do |t| > t.column :node_id, :integer, :null => false > t.column :related_node_id, :integer, :null => false > t.column :label, :string, :null => false, :default => '''' > end > add_index :edges, [:node_id, :related_node_id], :unique => true > end > def self.down > drop_table :edges > drop_table :nodes > end > end > > The two models are as follows: > > class Node < ActiveRecord::Base > validates_presence_of :title > has_many :edges, :dependent => true > has_many :related_nodes, :through => :edges, :class_name => > ''Node'', :foreign_key => ''node_id'' > end > > class Edge < ActiveRecord::Base > belongs_to :node > belongs_to :related_node, :class_name => ''Node'', :foreign_key => > ''related_node_id'' > validates_uniqueness_of :related_node_id, :scope => :node_id > validates_presence_of :node, :related_node > end > > In script/console I then create two nodes and link them with an edge as > follows: > > >> from_node = Node.create :title => ''From'' > >> to_node = Node.create :title => ''To'' > >> e = Edge.create :node => from_node, :related_node => to_node > >> from_node.edges.find_first.related_node > => #<Node:0xb7430ee4 @attributes={"body"=>"", "title"=>"To", "id"=>"2"}> > > SO FAR SO GOOD! but if I ask the ''from_node'' for ''related_nodes'' this is > what I get back!!! > > >> from_node.edges.related_nodes.find_first > => #<Node:0xb742e20c @attributes={"body"=>"", "title"=>"From", "id"=>"1"}> > > Same result even if I change :foreign_key in the Node model from ''node_id'' > to ''related_node_id''. Furthermore, :association_foreign_key is not accepted > as a parameter to has_many :through associations. > > Does anybody have a clue of what I am doing wrong here? Or is it that Rails > 1.1 does not support self-referential join models? > > Thanx in advance for the help and consideration, > > Edoardo "Dado" Marcora > > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >