How to access attribute in a self-referential many-to-many r

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

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

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!