Topic: Self referential - Many to many with extra attributes

I have been surfing the web for almost a week now, trying to find a way to read and write extra attributes in a join table, without success. So here i am putting my problem which is fairly simple and i believe is used in almost all the web application with a little complexity.

I want to create a friends system. smile

users { id, firstname, lastname}
friends {user_id, friend_id, status, created_at}

now i can create the connection through has_and_belongs_to_many - and i have seen loads of examples with "has_many, :through" - but none of the examples specified how in the world of ruby on rails would i be able to read and write the extra attributes e.g.

When user A selects a user B to be his/her friend then - a record be inserted into the friends table - user_id = user_A, friend_id = user_B, Status = 'pending', created_at = Date.today() - and - another record - user_id = USER_B, friend_id = USER_A, status = 'new request', created_at = Date.today()

and offcourse also read these extra attributes

Hope the issue is clear.. plz help

radical vision fuels disruptive technologies

Re: Self referential - Many to many with extra attributes

Wouldn't something like this work?

<% user = User.find(:first)%>
<% for friend in user.friends %>
    Hello <%= user.firstname %>, my name is <%= friend.firstname %>
<% end %>

Last edited by dahuk (2006-12-14 08:30:06)

Re: Self referential - Many to many with extra attributes

Yes, but i am looking for a construct to access status, and created_at in the join table "friends".

for example: When displaying the list of friends - i would be able to notify the user that a perticular friend has not accepted his friends request if the status attribute in the join table is set to pending - and - the created_at is good to keep track of when did they become friends smile

The example you have provided duhak is about accessing the attributes of user table not the extra attributes in the join table.

friend.status or friend.created_at would throw an unidentified constant error against status and created_on

thanks for replying anyways.

radical vision fuels disruptive technologies

Re: Self referential - Many to many with extra attributes

Sorry for not reading carefully enough, I shall try again though!

First I think you should rename your friends table to friendship, because what you modeling there is not a person but a relationship.

That would leave you with your users table and User model, and with a friendships table and a Friendship model. Instead of using has_and_belongs_to_many, you can do something like this.

class User < ActiveRecord::Base
    has_many :friendships
end

class Friendship < ActiveRecord::Base
    belongs_to :user
end


Then you could find when your first user made friends like this:

@user = User.find(:first)
@user.friendships.each {|relationship|
    #...
    releationship.created_at
    #...
}

But then you are not longer using join tables, which I don't know how to access the parameters of, since they do not have corresponding models.

Last edited by dahuk (2006-12-14 12:47:41)

Re: Self referential - Many to many with extra attributes

Yes, renaming Friend to Friendship is a good way to go. You can then do this:

class User < ActiveRecord::Base
  has_many :friendships
  has_many :friends, :through => :friendships #...
end

class Friendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, :class_name => 'User', :foreign_key => 'friend_id'
end

# in view
<% for friendship in @user.friendships %>
  <%= friendship.status %>
  <%= friendship.friend.firstname %>
<% end %>

Railscasts - Free Ruby on Rails Screencasts

Re: Self referential - Many to many with extra attributes

Thanks alot - duhak, thanks for bringing more clearity to my understanding of modeling relationships, and ryanb, it worked - thanks. you people saved the remaining hair on my head, otherwise i would have pulled them out too wink

Last edited by dagger007 (2006-12-14 18:27:23)

radical vision fuels disruptive technologies