# Self-referential habtm relationship

**URL:** <https://www.ruby-forum.com/t/self-referential-habtm-relationship/129093>\
**Category:** Rails\
**Created:** [February 14, 2008, 7:08am UTC](https://www.ruby-forum.com/t/self-referential-habtm-relationship/129093 "2008-02-14T07:08:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![dharmarth](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/3e96dc/32.png) [@dharmarth](https://www.ruby-forum.com/u/dharmarth)\
**Post date:** [February 14, 2008, 7:08am UTC](https://www.ruby-forum.com/t/self-referential-habtm-relationship/129093/1 "2008-02-14T07:08:26Z")

</div>

I have been working on making a self-referential habtm relationship that  
uses a join model because I want to store info about the relationship. I  
have been using Chad F.'s “Rails Recipes” as a guide. So far I have  
had little luck. Here is what I have that works a little, but not  
really:

class User \< ActiveRecord::Base  
has\_and\_belongs\_to\_many :friends,  
:class\_name=\>‘User’,  
:join\_table=\>‘friends’,  
:association\_foreign\_key=\>‘friend\_id’,  
:foreign\_key=\>‘user\_id’,  
:before\_add =\> :check\_self,  
:after\_add =\> :be\_friendly\_to\_friend,  
:after\_remove =\> :no\_more\_mr\_nice\_guy

def be\_friendly\_to\_friend(friend)  
friend.friends \<\< self unless friend.friends.include?(self)  
end

def no\_more\_mr\_nice\_guy(friend)  
friend.friends.delete(self) rescue nil  
end

def check\_self(friend)  
if self==friend then …  
end  
end

I want to prevent duplicate entries. When I do something like this

u1=User.find(1)  
u2=User.find(2)

u1.friends\<\<u2.friends

Then it is adding all the friends of u2 even if some of them were  
already there.  
And it is also adding itself as friend.

Can anyone tell me what I can write in before\_add callback so that I can  
prevent record from creation if it is meeting some condition.

Thanks  
Dharmarth

---

<div class="post-metadata">

**Author:** ![dharmarth](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/3e96dc/32.png) [@dharmarth](https://www.ruby-forum.com/u/dharmarth)\
**Post date:** [February 15, 2008, 8:14am UTC](https://www.ruby-forum.com/t/self-referential-habtm-relationship/129093/2 "2008-02-15T08:14:23Z")

</div>

Ilan B. wrote:

> Dharmarth S. wrote:
> 
> > u1=User.find(1)  
> > u2=User.find(2)
> > 
> > u1.friends\<\<u2.friends
> > 
> > Then it is adding all the friends of u2 even if some of them were  
> > already there.  
> > And it is also adding itself as friend.
> > 
> > Can anyone tell me what I can write in before\_add callback so that I can  
> > prevent record from creation if it is meeting some condition.
> > 
> > Thanks  
> > Dharmarth
> 
> friends\_to\_add = (u2.friends - u1.friends)  
> friends\_to\_add.delete u1  
> friends\_to\_add.each {|f| u1.friends \<\< f}
> 
> hth
> 
> ilan

Thank you very much ilan.

Is there any way so that i can throw an exception from before\_add  
callback and stop record creation??  
Because, if i have to repeate this thing every time then it is not  
DRY…

Thanks  
Dharmarth

---

<div class="post-metadata">

**Author:** ![dharmarth](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/3e96dc/32.png) [@dharmarth](https://www.ruby-forum.com/u/dharmarth)\
**Post date:** [February 14, 2008, 3:27pm UTC](https://www.ruby-forum.com/t/self-referential-habtm-relationship/129093/3 "2008-02-14T15:27:09Z")

</div>

Dharmarth S. wrote:

> u1=User.find(1)  
> u2=User.find(2)
> 
> u1.friends\<\<u2.friends
> 
> Then it is adding all the friends of u2 even if some of them were  
> already there.  
> And it is also adding itself as friend.
> 
> Can anyone tell me what I can write in before\_add callback so that I can  
> prevent record from creation if it is meeting some condition.
> 
> Thanks  
> Dharmarth

friends\_to\_add = (u2.friends - u1.friends)  
friends\_to\_add.delete u1  
friends\_to\_add.each {|f| u1.friends \<\< f}

hth

ilan
