RAILS:如何查询是否已有一个由一组用户组成的团队
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RAILS:如何查询是否已有一个由一组用户组成的团队相关的知识,希望对你有一定的参考价值。
我正在使用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
基本上我是从接口向API发送一组用户ID,我想查询是否已经有一个由我传递给API的用户(用户ID)组成的团队。
我已经尝试过这样做:
Team.joins(:team_users).where('team_users.user_id' => [3,5])
此查询的问题在于它返回包含id等于3或5的用户的每个团队。正确的结果是返回一个团队,其中包含用户3和5或5和3作为其团队成员。
提前致谢。
Update
最初的业务规则就是这样,有一个跟踪树木的应用程序,因此我有一个名为树的模型,当我们创建一个树时,必须说明哪个团队创建了这个树。所以我使用了select select用户下拉字段和select2 js库,这就是我将user_ids传递给API的方式。所以基本的想法是检查是否已经是由传递给API的用户组成的团队,如果已经有一个团队我使用它的id并说该树是由该团队注册的,如果没有团队与coposed只买我创建一个新团队的用户,并引用它的ID到树。
您可以通过不同方式解决问题。滚动每个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
Update
因此,您希望找到仅由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
我把它实现为
在key: string
和Team
模型中添加一个字段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
或用户= [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])
它可能对你有所帮助。谢谢
以上是关于RAILS:如何查询是否已有一个由一组用户组成的团队的主要内容,如果未能解决你的问题,请参考以下文章
C++ - 如何有效地找出向量中的任何字符串是不是可以由一组字母组合而成