我正在使用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我创建一个新团队并将其引用到树上。
答案 0 :(得分:0)
我已将其实现为
在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
或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