Forum: Ruby on Rails Pros/cons of doubling up in Self-Referential has_many via :t

Announcement (2017-05-07): is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see and for other Rails- und Ruby-related community platforms.
58c6efb8466b9f85155fe6aa9fc37fce?d=identicon&s=25 Chris T (Guest)
on 2006-04-17 18:38
(Received via mailing list)
Relative newbie so would welcome comments re structure of a
self-referential relationship I've got.

It's started off similar to the Person HABTM friends in the Rails
recipes books (working fine), but I needed to turn the join table into a
full-blown model as I wanted to add attributes to it. Few tricky bits
dealing with the new :through structure and understanding how :scope
worked but got there OK in the end with the help of the console and lots
of checking of the log.

Now, to the question. The relationship is a reflexive one -- i.e. if
person A has a relationship (of type i) with person B, then person B has
a relationship (of type i) with person A. In Rails Recipes (and in my
original HABTM setup), this was done by automatically adding a reverse
row to the relationships table using :after_add (and removing it with

Downside is that if the table has attributes (relationship_type, notes
on relationship) this starts to get a bit messy, meaning that every time
one is updated the reverse must be too. I could wrap this up in a
transaction, but somehow it seems a bit inelegant.

The other way -- which is how I've done it -- is to leave the
relationship with a single entry in the relationship table and add an
instance method to the model which bundles up those people who have who
have a relationship with A and all those who A has a relationship. Given
that I also want to get the relationship id, the notes and the
relationshiptype, I've got something like this (sorry for all the
relatee and relation_tos, etc):

def allrelations
    ar1 = self.relation_froms.find(:all, :include => :relator).collect
{|c| {"id" =>, "notes" =>c.notes, "reltype" => c.reltype, "person"
=>c.relator} }
    ar2 = self.relation_tos.find(:all, :include => :relatee).collect
{|d| {"id" =>, "notes" =>d.notes, "reltype" => c.reltype, "person""
=>d.relatee} }

I can then loop through them in the view, with something like this:
<% for r in @person.allrelations %>
    <%= h(r["person"].fullname) %> (<%= h(r["reltype"]) %>) <%=
h(r["notes"]) %><br />
  <% end %>

I'd welcome some comments on this (as I said, pretty noobish) -- am I
better off sticking with the original write-twice system? Will the
allrelations method get too heavy as the tables grow in size? Does the
idea (and/or code) suck?

Thanks in advance

Chris T
This topic is locked and can not be replied to.