# Self-Referential has\_many :through

**URL:** <https://www.ruby-forum.com/t/self-referential-has-many-through/100989>\
**Category:** Rails\
**Created:** [August 2, 2006, 12:42pm UTC](https://www.ruby-forum.com/t/self-referential-has-many-through/100989 "2006-08-02T12:42:10Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![rurounijones](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f1d935/32.png) [@rurounijones](https://www.ruby-forum.com/u/rurounijones)\
**Post date:** [August 2, 2006, 12:42pm UTC](https://www.ruby-forum.com/t/self-referential-has-many-through/100989/1 "2006-08-02T12:42:10Z")

</div>

Hello all.

I am trying to create a self-referential has\_many :through. I used the  
following site as a guide  
[http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through](http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through)  
but it still doesn’t appear to be working. I have two models. Person and  
Relationship. A person has many contacts (Which is another person)  
through relationships

class Person \< ActiveRecord::Base  
has\_many :relationship  
has\_many :contacts, :through =\> :relationship end  
end

class Relationship \< ActiveRecord::Base  
belongs\_to :person, :foreign\_key =\> “person\_id”  
belongs\_to :contact, :foreign\_key =\> “contact\_id”, :class\_name =\>  
“Person”  
end

If I use the code as above then while the relationships appear in the  
view the only “Contact” that appears is the Person I am currently  
looking at (So the Person “Person A” lists “Person A” as a contact).

If, on the other hand I do the following:

class Person \< ActiveRecord::Base  
has\_many :relationship  
has\_many :contacts, :through =\> :relationship end  
end

class Relationship \< ActiveRecord::Base  
belongs\_to :person, :foreign\_key =\> “person\_id”  
belongs\_to :contact, :foreign\_key =\> “contact\_id”  
end

class Contact \< ActiveRecord::Base  
set\_table\_name ‘people’  
end

It works fine. It appears that setting the :contact to :class\_name =\>  
“Person” screws up the relationship. I would rather avoid defining a  
separate “Contact” class and use self-referential but I cannot seem to  
do it.

Can anyone offer some advice?

Thanks

RJ

---

<div class="post-metadata">

**Author:** ![rurounijones](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f1d935/32.png) [@rurounijones](https://www.ruby-forum.com/u/rurounijones)\
**Post date:** [August 2, 2006, 8:13pm UTC](https://www.ruby-forum.com/t/self-referential-has-many-through/100989/2 "2006-08-02T20:13:21Z")

</div>

RurouniJones wrote:

> I am trying to create a self-referential has\_many :through. I used the  
> following site as a guide  
> [http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through](http://blog.hasmanythrough.com/articles/2006/04/21/self-referential-through)  
> but it still doesn’t appear to be working. I have two models. Person and  
> Relationship. A person has many contacts (Which is another person)  
> through relationships
> 
> class Person \< ActiveRecord::Base  
> has\_many :relationship  
> has\_many :contacts, :through =\> :relationship end  
> end
> 
> class Relationship \< ActiveRecord::Base  
> belongs\_to :person, :foreign\_key =\> “person\_id”  
> belongs\_to :contact, :foreign\_key =\> “contact\_id”, :class\_name =\>  
> “Person”  
> end
> 
> If I use the code as above then while the relationships appear in the  
> view the only “Contact” that appears is the Person I am currently  
> looking at (So the Person “Person A” lists “Person A” as a contact).
> 
> If, on the other hand I do the following:
> 
> class Person \< ActiveRecord::Base  
> has\_many :relationship  
> has\_many :contacts, :through =\> :relationship end  
> end
> 
> class Relationship \< ActiveRecord::Base  
> belongs\_to :person, :foreign\_key =\> “person\_id”  
> belongs\_to :contact, :foreign\_key =\> “contact\_id”  
> end
> 
> class Contact \< ActiveRecord::Base  
> set\_table\_name ‘people’  
> end
> 
> It works fine. It appears that setting the :contact to :class\_name =\>  
> “Person” screws up the relationship. I would rather avoid defining a  
> separate “Contact” class and use self-referential but I cannot seem to  
> do it.
> 
> Can anyone offer some advice?

Take another look at my article and you’ll see you left out a couple  
things. One, you are using teh singular :relationship for the has\_many  
association, and you should be using the plural :relationships. But more  
importantly, you don’t have a :class\_name option on the :contacts  
association. You are also missing the :people association to go the  
other direction in the mapping. And you seem to have a spurious “end” in  
your Person :contacts declaration. Not sure if those are email  
artifiacts or in your real code, so who knows.

You’re pretty close though. Just take another pass to make it work like  
described in the article and it should be fine.

–  
Josh S.  
[http://blog.hasmanythrough.com](http://blog.hasmanythrough.com)

---

<div class="post-metadata">

**Author:** ![rurounijones](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/f1d935/32.png) [@rurounijones](https://www.ruby-forum.com/u/rurounijones)\
**Post date:** [August 3, 2006, 12:42pm UTC](https://www.ruby-forum.com/t/self-referential-has-many-through/100989/3 "2006-08-03T12:42:31Z")

</div>

I was recently working on this exact same issue, and finally found  
another blog with a more descriptive solution (don’t recall where  
though). Here’s what I eventually came up with after reading that blog…

class User \< ActiveRecord::Base  
has\_many :users\_as\_buddies, :foreign\_key =\> “buddy\_id”, :class\_name =\>  
“BuddyList”  
has\_many :users\_as\_friends, :foreign\_key =\> “friend\_id”, :class\_name  
=\> “BuddyList”  
has\_many :buddies, :through =\> :users\_as\_friends  
has\_many :friends, :through =\> :users\_as\_buddies  
end

class BuddyList \< ActiveRecord::Base  
belongs\_to :friend, :foreign\_key =\> “friend\_id”, :class\_name =\> “User”  
belongs\_to :buddy, :foreign\_key =\> “buddy\_id”, :class\_name =\> “User”  
end

buddies; people I’ve added to my buddy list.  
friends; people who’ve added ME to THEIR buddy list.

buddies != friends

What happens is, if User A adds User B to their buddy list, User B adds  
User C to their own buddy list, and User C adds both User’s A and B to  
thier own buddy list, then…

@usera.buddies =\> UserB  
@usera.friends =\> UserC  
@userb.buddies =\> UserC  
@userb.friends =\> [UserA, UserC]  
@userc.buddies =\> [UserA, UserB]  
@userc.friends =\> UserB

Note that some people would want it so that if User A adds User B to his  
buddy list, then User A is automatically on User B’s buddy list. I’m  
sure this could be done programatically by adding a mirror image row to  
the buddy\_lists table every time a buddy list entry is created, but I’m  
not sure how to do that strictly through the model relationships.  
However, I didn’t want that “feature” for myself, so I wasn’t worried  
about it. YMMV.
