Ruby on rails Rails中两个关系的合并

Ruby on rails Rails中两个关系的合并,ruby-on-rails,ruby,activerecord,Ruby On Rails,Ruby,Activerecord,这应该很容易,我想 一个组织有一个所有者和成员——两者都是用户 这是由组织使用类名“用户”设置的,如: class Organisation < ApplicationRecord belongs_to :owner, class_name: "User", foreign_key: "owner_id" has_many :organisations_users has_many :members, class_name: "User", through: :organ

这应该很容易,我想

一个组织有一个所有者和成员——两者都是用户

这是由组织使用类名“用户”设置的,如:

class Organisation < ApplicationRecord
   belongs_to :owner, class_name: "User", foreign_key: "owner_id"
   has_many :organisations_users
   has_many :members, class_name: "User", through: :organisations_users, source: :user
end
这种方法可以工作,但返回的嵌套数组很难正确访问

  scope :all_members, joins(:members).merge(:owner)
这根本不起作用。可能是胡说八道

  def all_members
     members_array = members.dup
     members_array << owner
  end
def所有_成员
members\u数组=members.dup

成员\u array如果顺序不一定重要,那么我们可以将其放入单个查询中,如下所示:

如果轨道5

def all_members
  # not sure if you could just do 
  # owner.or(members) since they are both User 
  # but it seems unlikely due to the join table 
  User.where(id: self.owner_id).or(
    User.where(id: organisation_users.select(:user_id))
  )
end 
所有版本的Rails(小于并包括Rails 5)我们都可以使用
Arel
来构建更复杂的查询

def all_members
  user_table = User.arel_table   
  User.where(
    users_table[:id].eq(self.owner_id).or(
       users_table[:id].in(
         organisation_users.select(:user_id).arel
       )
    )
  ) 
end 
这两者都将产生以下SQL

SELECT users.* 
FROM users 
WHERE 
  (users.id = [YOUR_OWNER_ID] OR 
   users.id IN (
     SELECT organisations_users.user_id 
     FROM organisations_users
     WHERE organisations_users.organisation_id = [YOUR_ORGANISATION_ID]
  ))

最终结果将是
用户
对象的
ActiveRecord::Relation

如果顺序不一定重要,那么我们可以将其放入一个单独的查询中,如下所示:

如果轨道5

def all_members
  # not sure if you could just do 
  # owner.or(members) since they are both User 
  # but it seems unlikely due to the join table 
  User.where(id: self.owner_id).or(
    User.where(id: organisation_users.select(:user_id))
  )
end 
所有版本的Rails(小于并包括Rails 5)我们都可以使用
Arel
来构建更复杂的查询

def all_members
  user_table = User.arel_table   
  User.where(
    users_table[:id].eq(self.owner_id).or(
       users_table[:id].in(
         organisation_users.select(:user_id).arel
       )
    )
  ) 
end 
这两者都将产生以下SQL

SELECT users.* 
FROM users 
WHERE 
  (users.id = [YOUR_OWNER_ID] OR 
   users.id IN (
     SELECT organisations_users.user_id 
     FROM organisations_users
     WHERE organisations_users.organisation_id = [YOUR_ORGANISATION_ID]
  ))

最终结果将是
用户
对象的
ActiveRecord::Relation

如果获得一个数组就足够了,那么您可以简单地使用:

def all_members
  [owner] + members
end
如果您需要关系,那么最简单(但不是最有效)的方法是:

def all_members
  User.where(id: [owner] + members.ids)
end

这并不是最有效的,因为生成的SQL可能在
语句中包含一个相当大的
,数据库解析器无法有效地缓存该语句。但是,如果数字在几十个范围内,即使是这种关系技巧也足够了。

如果返回数组就足够了,那么您可以简单地使用:

def all_members
  [owner] + members
end
如果您需要关系,那么最简单(但不是最有效)的方法是:

def all_members
  User.where(id: [owner] + members.ids)
end

这并不是最有效的,因为生成的SQL可能在
语句中包含一个相当大的
,数据库解析器无法有效地缓存该语句。尽管如此,如果数字在几十个范围内,即使是这种关系技巧也足够了。

您可以使用splat操作符(
*
)将您的方法编写为
[*成员,所有者]
)。最好是有一个关系,将返回所有成员与一个查询虽然。嘿,这工作!我认为这可能是堆栈溢出所需的最小更改,它仍然进行2次选择,我的目标是优化。如果您将
组织用户
成员
之间的关系添加到问题中,您应该能够得到一个可接受的答案。concat(您可以使用splat操作符(
*
)将您的方法编写为
[*成员,所有者]
)。最好是使用一个查询返回所有成员的关系。嘿,这很有效!我认为这可能是堆栈溢出所需的最小更改。它仍有两个选择,我的目标是优化。如果您将
组织用户
成员
之间的关系添加到问题中,您应该d能够得到一个可接受的答案。concat(第二种情况应该是
User.where
而不仅仅是
where
,虽然我还没有测试过这个理论,但我可能会假设这应该是
[owner.id]+members.id
,这将导致3个查询(获取所有者,获取成员id,获取用户where.)正确,它将导致3个查询。我提到它不是非常有效的原因。第二种情况应该是
User。where
不仅仅是
where
,虽然我还没有测试这个理论,但我可能会假设这应该是
[owner.id]+members.id
,这将导致3个查询(fetchowner,fetchmemberid,fetchusers where。)正确,它将导致3个查询。我提到它效率不高的原因。