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个查询。我提到它效率不高的原因。