Creating reflective has_and_belongs_to

Hi I have a question is it possible to create the reflective relation with users and friends using has_and_belongs_to. I found this post that is partly connected to my: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/dff2032301961e2d

but my issue is join table "friends_users" where I would need to create duplication of data when the relationship is reflective: every time someone create the friend I need to add two rows to the join table (user, friend) and (friend, user) with just swapped ids. Is there any better way of handling this type of relations?

Piotr J. Puczyński

Piotr J. Puczyński wrote:

Hi I have a question is it possible to create the reflective relation with users and friends using has_and_belongs_to. I found this post that is partly connected to my: http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/dff2032301961e2d

but my issue is join table "friends_users" where I would need to create duplication of data when the relationship is reflective: every time someone create the friend I need to add two rows to the join table (user, friend) and (friend, user) with just swapped ids. Is there any better way of handling this type of relations?

Sure. One possibility (untested): create a join model (I'd call it Friendship) and, in its constructor, sort the two user IDs. That way, you don't need both (3, 5) and (5, 3); they both normalize to (3, 5), so that's all you have to search for.

Piotr J. Puczyński

Best,

Thank you for the message, Yes it is some idea for adding and removing friendships. But I still cannot imagine how this model will enable listing for friends of user x. user = User.find(id) comrades = user.friends

I think sorted model will not work in that case (it doesn't know in which column should it search).

Piotr J. Puczyński

OK. I also think the first option is better. However I don't know how to force the model to join based on two columns in join table so that I will be able to write simple 'user.friends' each time I need a friends' list. Do you know how to hack it?

Piotr J. Puczyński

Piotr Jacek Puczynski wrote:

OK. I also think the first option is better. However I don't know how to force the model to join based on two columns in join table so that I will be able to write simple 'user.friends' each time I need a friends' list. Do you know how to hack it?

See the article I pointed to. You'll either need a union query or two joins to the same table.

If you're going to do this, please make sure you understand the SQL involved. ActiveRecord exists to abstract, not to hide.

Piotr J. Puczyński

Best,

Hi. I was discussing the issue with one of my friends that teaches the databases course in the university and he said that more practically is to have this small duplication then to use slow outer join queries to list friends. The duplication in that case will not cause lot of space in database. It's worth to think of that argumentation.

Piotr Jacek Puczynski