# Has\_and\_belongs\_to\_many :self

**URL:** <https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971>\
**Category:** Rails\
**Created:** [January 9, 2006, 7:38pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971 "2006-01-09T19:38:56Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [January 9, 2006, 7:38pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/1 "2006-01-09T19:38:56Z")

</div>

Hi all

I got the following class:

class Member \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :buddies,  
:class\_name =\> ‘Member’,  
:join\_table =\> ‘members\_have\_buddies’,  
:foreign\_key =\> ‘member\_id’,  
:association\_foreign\_key =\> ‘buddy\_id’  
end

You can see that a member can have any other member as a “buddy”; these  
relationships are held in the table members\_have\_buddies (member\_id,  
buddy\_id).

So far, so good.  
I have a member “my\_member”, that has 3 other members marked as buddies,  
so I got 3 entries in the members\_have\_buddies table.  
When I delete my\_member, then the 3 entries in the table are also  
deleted, as I expect it to do.  
But when I delete one of the 3 other members, that are marked as  
members, then the related entry in the members\_have\_buddies table does  
_not_ get deleted!

I assume, this is an error, is it? Or have I done anything wrong? How  
can I solve this problem?

Thanks a lot for help.  
Josh

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [January 9, 2006, 7:53pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/2 "2006-01-09T19:53:02Z")

</div>

> When I delete my\_member, then the 3 entries in the table are also  
> deleted, as I expect it to do.  
> But when I delete one of the 3 other members, that are marked as  
> members, then the related entry in the members\_have\_buddies table does  
> _not_ get deleted!
> 
> I assume, this is an error, is it? Or have I done anything wrong? How  
> can I solve this problem?

i think it would be good to add a new association type to ActiveRecord  
called “friends\_with” or something since it seems that this is a pretty  
common case in the ‘social networking’ or ‘semantic web’ or whatever the  
bloggers are calling it this week…

for just tricking habtm into being this type of association, you could  
make the friendships bidirectional with callbacks, something like:

h\_a\_b\_t\_m :after\_add =\> :create\_reverse\_association, :after\_remove =\>  
:remove\_reverse\_association

def create\_reverse\_association(user)  
user.buddy \<\< self unless user.buddy.include?(self)  
end

def remove\_reverse\_association(user)  
user.buddy.delete(self) if user.buddy.include?(self)  
end

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [January 9, 2006, 10:26pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/3 "2006-01-09T22:26:52Z")

</div>

someone who replied off list said:

> i dont think you’ll ever convince \_\_\_\_\_ to add social-networking or other domain-specific …

right, “friends\_with” was a poor choice of words. intra-class  
bidirectional connections could be used for anything from ‘node maps’  
for a public transportation or computer network, to  
friendster/myspace/xanga/etc, to ‘see also’ dictionary definitions or  
wiki entries, product cross-sells, etc.

of course rails is already well suited to the task, but something like:

connections :name =\> ‘buddy’

is a lot simpler than the half a dozen things you have to do now wrt  
overriding the class name, adding callbacks, specifying foreign keys,  
etc…

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [May 16, 2009, 4:56am UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/4 "2009-05-16T04:56:37Z")

</div>

Joshua M. wrote:

> Hi all
> 
> I got the following class:
> 
> class Member \< ActiveRecord::Base  
> has\_and\_belongs\_to\_many :buddies,  
> :class\_name =\> ‘Member’,  
> :join\_table =\> ‘members\_have\_buddies’,  
> :foreign\_key =\> ‘member\_id’,  
> :association\_foreign\_key =\> ‘buddy\_id’  
> end
> 
> You can see that a member can have any other member as a “buddy”; these  
> relationships are held in the table members\_have\_buddies (member\_id,  
> buddy\_id).
> 
> So far, so good.  
> I have a member “my\_member”, that has 3 other members marked as buddies,  
> so I got 3 entries in the members\_have\_buddies table.  
> When I delete my\_member, then the 3 entries in the table are also  
> deleted, as I expect it to do.  
> But when I delete one of the 3 other members, that are marked as  
> members, then the related entry in the members\_have\_buddies table does  
> _not_ get deleted!
> 
> I assume, this is an error, is it? Or have I done anything wrong? How  
> can I solve this problem?
> 
> Thanks a lot for help.  
> Josh

Hi Josh,

I know you posted this while back, but I’m having a great deal of  
trouble with my habtm self-referencing setup and was wondering if you  
could help. I have the exact same set up as what you showed in your  
original post.

The problem I run into is that it seems the DB only saves in one  
direction, so if I make memberA have buddies memberB & memberC, when I  
call memberA.friends I get both memberB & memberC returned. However if I  
do memberB.friends I get no return. Same thing for memberC.friends.

And since the db only saves uni-directionally, it’s not letting me  
assign the other way around and make memberA a buddy under memberB or C.

Any suggestions on how to address this and make it so I can store and  
retrieve accurate friend connections?

Thanks!

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [January 11, 2006, 1:53pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/5 "2006-01-11T13:53:37Z")

</div>

carmen wrote:

> someone who replied off list said:
> 
> > i dont think you’ll ever convince \_\_\_\_\_ to add social-networking or other domain-specific …
> 
> right, “friends\_with” was a poor choice of words. intra-class  
> bidirectional connections could be used for anything from ‘node maps’  
> for a public transportation or computer network, to  
> friendster/myspace/xanga/etc, to ‘see also’ dictionary definitions or  
> wiki entries, product cross-sells, etc.
> 
> of course rails is already well suited to the task, but something like:
> 
> connections :name =\> ‘buddy’
> 
> is a lot simpler than the half a dozen things you have to do now wrt  
> overriding the class name, adding callbacks, specifying foreign keys,  
> etc…

Thanks a lot for your replies. I tried it with another habtm and it  
worked, as you suggested.  
Now what about “connections :name =\> ‘buddy’”? This doesn’t really  
exist, does it?

Btw. is there a way to be noticed when someone replies to my topic?

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [May 16, 2009, 10:25pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/6 "2009-05-16T22:25:51Z")

</div>

Joshua M. wrote:

> > Any suggestions on how to address this and make it so I can store and  
> > retrieve accurate friend connections?
> > 
> > Thanks!
> 
> Hi there
> 
> I’m not at my computer right now and will try to respond some time  
> later, but maybe you should try to really save the models and force a  
> reload on the already loaded ones…? Don’t know if this could cause the  
> problem…

Thanks Joshua,

I’ve searched around a bit and it seems that other people have run into  
this same issue. I’ve added some extra sql into my model now which will  
write the opposite direction record into the join table explicitly any  
time a relationship is made. So 1.friends(2) now leads to a join table  
of:

1 | 2  
2 | 1

Whereas before it would just be:

1 | 2

This seems to solve the problem for me, but it feels a bit hacky. I’m  
curious as to whether or not you had to do something extra like this to  
get the joins saving bi-directionally?

I have a different issue now as well, only relationships to new objects  
are being saved. So:

```
member1.buddies[0] = member2
member1.save

```

Doesn’t record anything to the join table. However:

```
member1.buddies[0] = Member.new
member1.save

```

saves the relationship to the join table correctly. The discrepency  
seems totally strange to me, any clues on that problem?

Thanks!

---

<div class="post-metadata">

**Author:** ![josh](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/45deac/32.png) [@josh](https://www.ruby-forum.com/u/josh)\
**Post date:** [May 16, 2009, 8:02pm UTC](https://www.ruby-forum.com/t/has-and-belongs-to-many-self/51971/7 "2009-05-16T20:02:07Z")

</div>

> Any suggestions on how to address this and make it so I can store and  
> retrieve accurate friend connections?
> 
> Thanks!

Hi there

I’m not at my computer right now and will try to respond some time  
later, but maybe you should try to really save the models and force a  
reload on the already loaded ones…? Don’t know if this could cause the  
problem…
