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 >>