[newbie] Symmetric relationships

I think the proper way of modelling this kind of relationship is to have two entries in the Relationships table. Otherwise, the semantics of the fields change depending on which way you are looking at the relationship.

So rather than having mem,ber and member2, you would have relationship_owner and related_person, where your model class should take care of creating both relationship entries in a add_relationship method or similar. This will also make your queries a lot easier. For example, for a father/son relationship, you will have:

relationship_owner related_person relationship
Daddy Bob Little Joe Son
Little Joe Daddy Bob Father

When you are querying for everybody who is a son, you only need to look for a “Son” relationship, rather than having endless conditions on (member=some_id and relationship=‘Son’) OR (member_2=some_id and relationship=‘Father’)


I'm facing a similar problem except that any given individual can have many
relationships. For example, Daddy Bob may be Little Joe's father. At the
same time, he might also be Suzy Q's husband and Little O. Annie's employer.

How would you model that kind of networked relationship?

(sorry to hijack this thread, but I'm guessing this is an issue others may
have as well.)

Max Muermann-3 wrote:

This layout for a relationship table models a many-to-many relationship between entries for people. There hsould not be anything else you need to do, except add more rows:

relationship_owner related_person relationship
Daddy Bob Little Joe Son
Little Joe Daddy Bob Father
Daddy Bob Annie Wife

Annie Daddy Bob Husband

Just make sure that your model creteas the appropriate reverse relationship, for example:

class Person < ActiveRecord::Base

reverse_relationships = [



def relate_to(person, relationship)

r1 = Relationship.create do |r|
   r.owner = this
   r.related_person = person
   r.relationship = relationship

r2 = Relationship.create do |r|

   r.owner = person

   r.related_person = this

   r.relationship = reverse_relationships[relationship.intern].to_s




Note that this does not make a distinction between Son/Daughter or Mother/Father.

If you have your has_many :through set up right, you can then use Person.find(1).relationships.

You can even use association extensions:

has_many :related_people, :through=>:relationship do
def relation(type_of_relationship)
find(:all, :conditions=>[ ‘relationship_type=?’, type_of_relationship ]


You can then do:

dad = Person.find(1)
children = dad.related_people.relation(‘Child’)

As the association extension automatically sets the scope to the parent relationship (parent and relationship here are in relational database terms).