【问题标题】:rails complex many-to-many queryrails 复杂的多对多查询
【发布时间】:2011-04-08 05:19:53
【问题描述】:

我有 3 个模型:用户、团队和成员 -

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

而且,我不太清楚如何在 User 模型中编写 team_mates 方法。它应该返回与 current_user 组中的其他用户的数组。我的想法是我应该使用范围来限制 Team 只包括当前用户是成员的团队,但我不太清楚语法。对此的任何帮助将不胜感激。

谢谢!

【问题讨论】:

    标签: ruby-on-rails-3 scope many-to-many


    【解决方案1】:

    使用成员资格表查找与您正在调用该方法的用户共享任何团队的用户。然后要过滤掉与当前用户共享超过 1 个团队的重复用户,请使用 distinct。

    我没有测试下面的代码,但希望它能让你走上正确的道路:

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

    更新

    看起来该答案中的某些 Arel 方法无法轻松映射回 ActiveRecord 领域。 (如果有人知道怎么做,我很想知道!)它还返回“当前用户”。试试这个:

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

    【讨论】:

    • 谢谢!看起来我们正在接近解决方案。我也必须将 User 转换为 socoped.table 才能使联接起作用。但是,现在该函数返回的是 Arel::SelectManager 而不是用户数组。知道如何从 Arel::SelectManager 中提取用户数组吗?这是我的代码(对于糟糕的格式感到抱歉):def team_mates m = Membership.scoped.table u = User.scoped.table u.join(m).where(m[:team_id].in(team_ids)).project('distinct users.*') end
    • 我正在谷歌搜索如何将其转换回 ActiveRecord Relation 对象,这正是您想要的。您可能可以获取最后一条语句的结果并执行.to_sql,然后将其传递给User.find_by_sqldef team_mates; m = Membership.scoped.table; u = User.scoped.table; sql = u.join(m).where(m[:team_id].in(team_ids)).project('distinct users.*').to_sql; User.find_by_sql(sql); end
    • 完美!太感谢了。这太棒了,你为我节省了很多时间,以至于我现在可以在 Arel 上阅读一堆东西 :) 我在书呆子天堂。
    【解决方案2】:

    怎么样?

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

    【讨论】:

      【解决方案3】:

      可能是这样的

      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
      

      这里有更多信息:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多