Self-Referential Many-To-Many relationships where the relati


#1

Trying to model a bunch of users that have friends that are other
users. clearly a job for has_and_belongs_to_many, but the trick is,
they have ratings for their friends. I have gone through the Rails
Recipes book, and it seems like I’m trying to combine the
self-referential many-to-many recipe (12) and the many to many
relationships where the relationship itself has data recipe (16). So
users have unique names, and friendships have user_id’s, friend_id’s,
and ratings. And here’s the model code:

class User < ActiveRecord::Base
has_and_belongs_to_many :all_friends,
:class_name => “User”,
:join_table => “friendships”,
:foreign_key => “user_id”,
:association_foreign_key => “friend_id”

has_and_belongs_to_many :close_friends,
:class_name => “User”,
:join_table => “friendships”,
:foreign_key => “user_id”,
:association_foreign_key => “friend_id”,
:conditions => “rating > 1”
end

class Friendship < ActiveRecord::Base
belongs_to :user
end

And everything works fine when I manually add friendships through the
console. And I can do things like:

user = User.find(:first)
=> #<User:0x25879f4 @attributes={“id”=>“2”, “name”=>“jordan”}>

user.all_friends
=> [#<User:0x257f358 @attributes={“rating”=>“1”, “id”=>“2”,
“user_id”=>“2”, “name”=>“bob”, “friend_id”=>“4”}>, #<User:0x257f31c
@attributes={“rating”=>“2”, “id”=>“1”, “user_id”=>“2”, “name”=>“adam”,
“friend_id”=>“3”}>]

user.close_friends
=> [#<User:0x257f31c @attributes={“rating”=>“2”, “id”=>“1”,
“user_id”=>“2”, “name”=>“adam”, “friend_id”=>“3”}>]

But now if I try to change the rating, it seems to cause problems:

friends = user.all_friends
f = friends[0]
=> #<User:0x257f358 @attributes={“rating”=>“1”, “id”=>“2”,
“user_id”=>“2”, “name”=>“bob”, “friend_id”=>“4”},
@new_record_before_save=nil, @errors=#<ActiveRecord::Errors:0x2579ee4
@errors={}, @base=#<User:0x257f358 …>>>

f.rating = 2
=> 2

f.save
ActiveRecord::StatementInvalid: Mysql::Error: Duplicate entry ‘bob’
for key 2: UPDATE users SET name = ‘bob’ WHERE id = 2
[… Errors snipped …]

So there’s a few strange things happening here. First off, it’s only
updating the User record, not the Friendship record, which makes
sense, since f is a User, but it doesn’t help me save the rating.
Also, the id that it is using is the id of the friendship record that
this friend was gathered ‘through’ (through in quotes because it’s not
using :through, which is what I’d like to do, but then I don’t know
how I would get the rating for a friendship), and not the id of the
User, so it’s trying to update the wrong User. This causes an error
cause now it’s updating some other User with the same name as the User
that we’re looking at, and names have to be unique.

So how should I be doing this? Also, have I found a bug in RoR? If so,
should I file it? (I’m capable of that, I’m sure…maybe even capable
of fixing it…who knows…).

Thanks in advance for any thoughts anyone has on the matter, maybe
suggestions about how I can do all of this better?


Cheers,
Jordan F.
removed_email_address@domain.invalid