RAILS:如何查询是否已经有一组用户组成的团队

时间:2017-12-20 05:59:06

标签: sql ruby-on-rails activerecord

我正在使用rails API,更具体地说是在创建操作中。

我的工作流程是这样的,我有两个rails应用程序,一个是API,另一个是接口。 API管理不同的后端操作,以便处理数据,存储数据,并以json格式响应接口。该接口充当前端,只是向API发出http请求以显示信息。

在我的API中,我有以下3种型号:

class Team < ApplicationRecord
  has_many :team_users
  has_many :users, through: :team_users
end

class User <ApplicationRecord
  has_many :team_users
  has_many :teams, through: :team_users
end

class TeamUser < ApplicationRecord
  belongs_to :user
  belongs_to :team
end

基本上我将一组用户ID从接口发送到API,我想查询一下是否已经有一个由用户(用户ID)组成的团队我已经转到了API。

我已经尝试过这样做:

Team.joins(:team_users).where('team_users.user_id' => [3,5])

此查询的问题在于它返回包含id等于3或5的用户的每个团队。正确的结果是返回一个具有用户3和5或5和3的团队作为他们的团队成员。

提前致谢。

更新

最初的业务规则就是这样,有一个跟踪树木的应用程序,所以我有一个名为树的模型,当我们创建一个树时,必须说明哪个团队创建了这个树。所以我使用了一个带有select2 js库的多选用户下拉字段,这就是我将user_ids传递给API的方式。因此,基本的想法是检查是否已经是由传递给API的用户组成的团队,如果已经有一个团队我使用它的id并且说该树是由该团队注册的,如果有insn& #39; ta co with coposed only buy the users我创建一个新团队并将其引用到树上。

2 个答案:

答案 0 :(得分:0)

我已将其实现为

key: stringTeam模型

中添加字段Team
class Team < ApplicationRecord
  has_many :team_users
  has_many :users, through: :team_users
  #callback
  before_validation :update_key

  def update_key
    self.key = Team.key_for_users(self.users)
  end

  def self.key_for_users(users)
    users.sort.map(&:id).join("_")
  end
end

所以基本上在这个回调之后,无论何时你创建一个团队,都会有一个密钥 例如: -

users = [3,5]

然后,团队中的key将为3_5

或users = [5,3]

然后,团队中的key将为5_3

从中我们可以很容易地得到你想要的结果

示例: -

user_ids = [3,5]
[14] pry(main)> user_ids_simple = user_ids.join('_')
=> "3_5"
[15] pry(main)> user_ids_reverse = user_ids.reverse.join('_')
=> "5_3"

和查询将是这样的: -

Team.where("key IN (?)",[user_ids_simple, user_ids_reverse])

它可能对您有所帮助。感谢

答案 1 :(得分:0)

您可以通过不同方式解决问题。滚动每个Team记录以检查它是否包含关联的user_ids非常简单但效率低下:

team.user_ids.sort == user_ids.sort

但是我们可以通过逆转过程使其变得高效,即迭代user_ids以找出相应的团队,取Team个ID并最终检查是否有任何team_id成立那些user_ids。如果已经由用户(user ids)组建了一个团队,则该行将返回 true

user_ids.map { |id| User.find(id).team_ids }.reduce(:&).present?

您可以将其包含在User类范围内,如下所示:

class User < ApplicationRecord
  ...
  def self.team_exists_for?(user_ids)
    # return early

    # what should it return when user_ids is empty
    # return ??? if user_ids.blank?

    # what should it return when any of the id is absent from :users table
    # set_of_all_user_ids = Set.new(User.pluck(:id))
    # set_of_user_ids     = Set.new(user_ids)
    # return ??? unless set_of_user_ids.subset? set_of_all_user_ids

    # finally
    user_ids.map { |id| User.find(id).team_ids }.reduce(:&).present?
  end
  ...
end

更新

因此,您希望找到具有user_ids提供的用户的团队,或者创建一个团队并分配回Tree模型实例。结合上述两种方法并在团队模型中定义范围本身似乎是一种更好的解决方案。

class Team < ApplicationRecord
  ...
  def self.find_or_create_for(user_ids)
    # find all team_ids which contain user_ids (inclusive)
    team_ids = user_ids.map { |id| User.find(id).team_ids }.reduce(:&).flatten

    if team_ids.present? # search for the team which ONLY has 'user_ids'
      team_id = team_ids.find { |id| Team.find(id).user_ids.sort == user_ids.sort }
    end

    return Team.find(team_id) if team_id

    # or create a team with user_ids and return
    team = Team.create! # create a team with required attributes
    team.user_ids = user_ids
    team
  end
  ...
end