Volte
Volte

Reputation: 1905

Ruby ActiveRecord multiple joins through associations

I'd like to convert

SELECT `users`.* FROM `users`
INNER JOIN `memberships`
    ON `memberships`.`user_id` = `users`.`id`
INNER JOIN `roles`
    ON `roles`.`id` = `memberships`.`role_id`
WHERE `memberships`.`group_id` = 'NUCC' AND (expiration > '2012-07-02')
ORDER BY `roles`.`rank` DESC

Into an ActiveRecord association.

Groups have many members (class User) through memberships. Each membership has a role (role_id) which maps to another table (roles) and subsequently an AR model (Role). Each role has a rank (integer) associated with it.

I'd like to simply sort the members of a group by the memberships-roles-rank.

Upvotes: 2

Views: 7329

Answers (1)

pdkl95
pdkl95

Reputation: 187

Untested, probably has typos, but...

class User < ActiveRecord::Base
  has_many :memberships
  has_many :roles, :through => :memberships, :uniq => true
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :role
end

class Role < ActiveRecord::Base
  has_many :memberships
  has_many :users, :through => :memberships, :uniq => true
end

And then, to sort the users by roles.rank:

q = User.joins(:memberships => :users)
q = q.where(:memberships.group_id => 'NUCC')
q = q.where("expressionn > '2012-07-02'")
q = q.order("roles.rank DESC")
puts q.to_sql

AREL lets you join things up like that pretty easily. For instance, you can keep that going with even further INNER JOINS with syntax similar to:

User.joins(:memberships => { :users => :someothermodel })

Just remember to replicate that structure whenever you need to reference something through the JOIN, or just write your own SQL fragment..

Upvotes: 2

Related Questions