Zag zag..
Zag zag..

Reputation: 6231

ActiveRecord, double belongs_to

I have 2 models: Link and User such as:

class Link < ActiveRecord::Base
  belongs_to :src_user
  belongs_to :dst_user
end

class User < ActiveRecord::Base
  has_many :links
end

A schema could looking like:

+----------+     +------+
| Link     |     | User |
+----------+     |------+
| src_user |---->|      |
| dst_user |---->|      |
+----------+     +------+

My question is: how can I edit User model do in order to do this

@user.links # => [list of links]

(...which should query @user.src_users + @users.dst_users, with unicity if possible.)

Can we do this only using SQL inside ActiveRecord? Many thanks.

(note: I'm on Rails 3.1.1)

Upvotes: 1

Views: 1213

Answers (2)

jamie_gaskins
jamie_gaskins

Reputation: 106

You have to specify multiple relations inside the user model so it knows which specific association it will attach to.

class Link < ActiveRecord::Base
  belongs_to :src_user, class_name: 'User'
  belongs_to :dst_user, class_name: 'User'
end

class User < ActiveRecord::Base
  has_many :src_links, class_name: 'Link', inverse_of: :src_user
  has_many :dst_links, class_name: 'Link', inverse_of: :dst_user
end

The :class_name option must be specified since the association name is not simply :links. You may also need to specify the :inverse_of option in the Link model, but I can't be sure of that. It wouldn't hurt if you did, though.

In order to do your @user.links call, you'll have to do something like this:

class User < ActiveRecord::Base
  def links
    Link.where(['src_user = ? OR dst_user = ?', self.id, self.id])
  end
end

… since ActiveRecord doesn't provide a way to merge two associations on the same model into one.

Upvotes: 3

jefflunt
jefflunt

Reputation: 33954

This sounds very similar to the child/mother/father problem, which has a solution. That is, a problem where an object of one type belongs_to more than one object of the same type (not necessarily the same type as the child, but the objects it belongs to are themselves the same type).

This solution is quite old, and may not be up to date with the latest style schemes in Rails3, but it should work fine, or with very little modification. http://railsforum.com/viewtopic.php?id=1248

Upvotes: 0

Related Questions