在Rails中合并两个关系

时间:2018-11-07 15:30:34

标签: ruby-on-rails ruby activerecord

我认为这应该很容易...

一个组织有一个所有者和成员-都是用户。

这是组织使用class_name:“ User”设置的,就像这样:

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

这可行,但是我需要一个all_members函数(或作用域),因此我可以在一个数组(或ActiveRecord对象)中同时获取所有者和成员。我以为这是微不足道的,但实际上并非如此。

我尝试过:

def all_members
   members << owner
end

这当然不是我想要的...每次我叫它时,都会将所有者添加到员工中。

def all_members
   [owner, members]
end

这种工作方式,但是返回一个嵌套数组,很难正确访问。

  scope :all_members, joins(:members).merge(:owner)

这根本不起作用。可能是胡说八道。

  def all_members
     members_array = members.dup
     members_array << owner
  end

这仍然会永久更改成员以包括所有者?!

帮助! (谢谢)

2 个答案:

答案 0 :(得分:1)

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

如果Rails 5

InvalidDate "\1058\1077\1082\1089\1090, \1082\1086\1090\1086\1088\1099\1081 \1074\1099 \1074\1074\1077\1083\1080 - \1101\1090\1086 \1082\1072\1082\1072\1103-\1090\1086 \1073\1077\1083\1080\1073\1077\1088\1076\1072!"

所有版本的Rails(低于并包括Rails 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 来构建更复杂的查询

Arel

这些都将导致以下SQL

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 

最终结果将是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

答案 1 :(得分:1)

如果取回一个阵列就足够了,那么您可以简单地使用:

def all_members
  [owner] + members
end

如果需要联系,那么最简单(但不是最有效)的方法是:

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

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