Take the 2-minute tour ×

I am trying to build a relationship model between users. A user can either initiate a relation, or receive a relation from another user. Therefore, the relations table in the db has the foreign keys "initiator_id" and "recipient_id".
Now, I can figure what relations the user initiated or received using the following associations:

has_many :initiated_relations, :foreign_key => :initiator_id, :class_name => 'Relation', :dependent => :destroy
has_many :received_relations,  :foreign_key => :recipient_id, :class_name => 'Relation', :dependent => :destroy

What I am trying to do, is build an association that will fetch me all relations that belong to a user (either initiated or received). Trying the following does not work, and complains about the lack of "user_id" field:

has_many :relations, :conditions => 'recipient_id = #{id} or initiator_id = #{id}'

How can I create an association that is solely based on the conditions field, without looking for the default foreign_key? Or is there perhaps a completely different approach to solving this?

share|improve this question

2 Answers 2

up vote 3 down vote accepted

Well, I can think of using finder_sql for that:

has_many :relations, :finder_sql => 'select * from relations right outer join users
    on relations.recipient_id = #{id} or relations.initiator_id = #{id}'

Apart from that, you can just write a method that will return a united array of the two relations associations', but you will lose the advantage of an association interface (phew).

Perhaps someone will come up with a better solution.

share|improve this answer
I already tried using finder_sql, however if there is any other way to achieve this I would prefer that, because with finder_sql I lose all functionality of associations. e.g: I can't do user.relations.find(:all, :conditions => {:confirmed => true}) or any other such function. Thanx for your input though, much appreciated. –  Faisal Oct 25 '10 at 9:04
i don't think this works. #{id} is evaluated at the class level, not the instance. it would need to be a proc, which as of rails v3.2.13 is only supported on :conditions option. Rails 4 will be much better for this stuff. –  Peter P. May 11 '13 at 0:18

From your comments to @neutrino's answer I understand, that you only need this "releation" for read only operations. If you're on Rails 3 you can utilize the fact, that it uses lazy fetching. The where() method returns ActiveRecord::Relation object, which you can later modify. So you can define a method like this:

def User < ActiveRecord::Base
  def all_relations
    Relation.where("initiator_id => ? OR recipient_id = ?", id, id)

And then you can do:

User.all_relations.where(:confirmed => true).all
share|improve this answer
This seems like a very elegant solution, and yes, I only want this relation for read-only purposes. However, I am not using Rails 3, so this won't work for me :(. +1 for the great answer though :). –  Faisal Oct 26 '10 at 7:06

Your Answer


