Renaud Richardet
2006-Aug-15 23:34 UTC
[Rails] How to access attribute in a self-referential many-to-many relationship
Hello List, I created a self-referential many-to-many relationship (as described in the book Rails recipe #18), where I have a model that has many-to-many relationships with itself. In this case, it''s person who can become friends. The join table looks like this: mysql> select * from friends_people; +-----------+-----------+-----------+ | person_id | friend_id | confirmed | +-----------+-----------+-----------+ | 1 | 2 | NULL | | 2 | 1 | NULL | | 1 | 3 | NULL | | 3 | 1 | NULL | and the people table is mysql> select * from people; +-------------+ | id | name | +----+--------+ | 1 | ren | | 2 | amy | +----+--------+ I have a model for person.rb, but none for friends_people. I can add friends like this: person1.friends << person2 Now the question is: how do I access the boolean "confirmed" from my model person.rb? Is this possible, and what is the best way? Thanks in advance, Renaud
Cameron Price
2006-Aug-16 00:23 UTC
[Rails] How to access attribute in a self-referential many-to-many relationship
This is probably the best article to read about this: http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through In your case (and shamelessly ripping off Josh''s code replacing Edge with Friendship and Node with User) it might be a bit like this: create_table "users" do |t| t.column "name", :string end create_table "friendships" do |t| t.column "source_id", :integer, :null => false t.column "sink_id", :integer, :null => false t.column "confirmed", :boolean class Friendship < ActiveRecord::Base belongs_to :source, :foreign_key => "source_id", :class_name => "User" belongs_to :sink, :foreign_key => "sink_id", :class_name => "User" end class User < ActiveRecord::Base has_many :friendships_as_source, :foreign_key => ''source_id'', :class_name => ''Friendship'' has_many :friendships_as_sink, :foreign_key => ''sink_id'', :class_name => ''Friendship'' has_many :people_who_like_me, :through => :friendships_as_sink has_many :people_i_like, :through => :friendships_as_source end now, depending on your specific needs, you can reference user.friendships_as_source.select {|friendship| friendship.confirmed} or similar. Cameron On 8/15/06, Renaud Richardet <renaud.richardet@gmail.com> wrote:> Hello List, > > I created a self-referential many-to-many relationship (as described > in the book Rails recipe #18), where I have a model that has > many-to-many relationships with itself. In this case, it''s person who > can become friends. The join table looks like this: > > mysql> select * from friends_people; > +-----------+-----------+-----------+ > | person_id | friend_id | confirmed | > +-----------+-----------+-----------+ > | 1 | 2 | NULL | > | 2 | 1 | NULL | > | 1 | 3 | NULL | > | 3 | 1 | NULL | > > and the people table is > mysql> select * from people; > +-------------+ > | id | name | > +----+--------+ > | 1 | ren | > | 2 | amy | > +----+--------+ > > I have a model for person.rb, but none for friends_people. I can add > friends like this: > person1.friends << person2 > > Now the question is: how do I access the boolean "confirmed" from my > model person.rb? Is this possible, and what is the best way? > > Thanks in advance, > Renaud > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Renaud Richardet
2006-Aug-17 00:17 UTC
[Rails] How to access attribute in a self-referential many-to-many relationship
Thank you Cameron, this works well. However, I''m not sure how to access the "friends": >> person1.find_all_in_people_i_like /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/associations.rb:873: warning: instance variable @people_i_like not initialized ActiveRecord::HasManyThroughSourceAssociationNotFoundError: ActiveRecord::HasManyThroughSourceAssociationNotFoundError but this works: person1.find_all_in_friendships_as_source also, is there a easier way to create new friends than: person1.friendships_as_source.create(:sink_id =>33, :confirmed => true) Any hints? Thanks, Renaud PS: the Rails community rocks, I am very impressed! Cameron Price wrote:> This is probably the best article to read about this: > > http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through > > > In your case (and shamelessly ripping off Josh''s code replacing Edge > with Friendship and Node with User) it might be a bit like this: > > create_table "users" do |t| > t.column "name", :string > end > create_table "friendships" do |t| > t.column "source_id", :integer, :null => false > t.column "sink_id", :integer, :null => false > t.column "confirmed", :boolean > > class Friendship < ActiveRecord::Base > belongs_to :source, :foreign_key => "source_id", :class_name => "User" > belongs_to :sink, :foreign_key => "sink_id", :class_name => "User" > end > > class User < ActiveRecord::Base > has_many :friendships_as_source, :foreign_key => ''source_id'', > :class_name => ''Friendship'' > has_many :friendships_as_sink, :foreign_key => ''sink_id'', > :class_name => ''Friendship'' > has_many :people_who_like_me, :through => :friendships_as_sink > has_many :people_i_like, :through => :friendships_as_source > end > > now, depending on your specific needs, you can reference > > user.friendships_as_source.select {|friendship| friendship.confirmed} > > or similar. > > Cameron > > On 8/15/06, Renaud Richardet <renaud.richardet@gmail.com> wrote: >> Hello List, >> >> I created a self-referential many-to-many relationship (as described >> in the book Rails recipe #18), where I have a model that has >> many-to-many relationships with itself. In this case, it''s person who >> can become friends. The join table looks like this: >> >> mysql> select * from friends_people; >> +-----------+-----------+-----------+ >> | person_id | friend_id | confirmed | >> +-----------+-----------+-----------+ >> | 1 | 2 | NULL | >> | 2 | 1 | NULL | >> | 1 | 3 | NULL | >> | 3 | 1 | NULL | >> >> and the people table is >> mysql> select * from people; >> +-------------+ >> | id | name | >> +----+--------+ >> | 1 | ren | >> | 2 | amy | >> +----+--------+ >> >> I have a model for person.rb, but none for friends_people. I can add >> friends like this: >> person1.friends << person2 >> >> Now the question is: how do I access the boolean "confirmed" from my >> model person.rb? Is this possible, and what is the best way? >> >> Thanks in advance, >> Renaud >>