开发者

rails complex many-to-many query

开发者 https://www.devze.com 2023-02-23 03:06 出处:网络
I\'ve got 3 models: User, Team, and Membership - class Team < ActiveRecord::Base has_many :memberships

I've got 3 models: User, Team, and Membership -

class Team < ActiveRecord::Base
  has_many :memberships
  has_many :members, :through => :memberships, :source => :user
end

class User < ActiveRecord::Base
  has_many :memberships, :dependent => :destroy
  has_many :teams, :through => :memberships

  def team_mates
    teams = Team.where(:members => id)
    team_mates = teams.members
  end
end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :team

  validates :user_id, :presence => true
  validates :team_id, :presence => true
end

And, I can't quite figure out how to write the team_mates method in the User model. It should return an array of the other users that are in a team with the current_user. My thought is that I should be useing a scope to limit Team to only include tea开发者_如何学Goms where the current user is a member but I can't quite figure out the syntax. Any help on this would be greatly appreciated.

Thanks!


Use the membership table to find users who share any team with the user you are calling the method on. Then to filter out duplicate users who share more than 1 team with current user, use distinct.

I haven't tested the below code, but hopefully it will get you on the right path:

def team_mates
  m = Membership.scoped.table
  Users.join(m).where(m[:team_id].in(team_ids)).project('distinct users.*')
end

UPDATE

Looks like some of the Arel methods in that answer don't have an easy mapping back to ActiveRecord land. (If someone knows how, I'd love to know!) And also it returns the 'current user'. Try this instead:

def team_mates
  User.joins(:memberships).where('memberships.team_id' => team_ids).where(['users.id != ?', self.id]).select('distinct users.*')
end


How about?

User.joins(:memberships).joins(:teams).where("teams.id" => id).uniq


Maybe something like this

scope team_mates, lambda {|user_id, teams| joins(:memberships).where(:team_id => teams, :user_id => user_id)}

def team_mates
  User.team_mates(self.id, self.teams.collect {|t| t.id})
end

Here is more info:

http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html

0

精彩评论

暂无评论...
验证码 换一张
取 消