11

我有一个组织模型(嵌套集)。我有一个人的模型。一个人可以有另一个人作为代理人。一个组织归一个人所有。组织仅对所有者或其代理人可见。

我想检索给定人可见的所有组织,即。由该人拥有或由该人拥有的所有组织,该人是其代表:

o = Arel::Table.new(:organisations)
p = Arel::Table.new(:people)
pd = p.where(p[:id].eq(3).or(p[:deputy_id].eq(3))).project(:id)
op = o.join(p).where(o[:person_id].in(pd)).project("distinct organisations.*)

可能有更好的方法来制定最后一个联接,但我想将人员及其代表的查询与人员及其代表可见的组织的查询分开。

最后一个连接返回一个 Arel::SelectManager (似乎没有任何有用的文档)。

有没有办法将 SelectManager 转换回 ActiveRecord::Relation 以从“组合下的闭包”的整个概念中受益?

如何再次自行加入上述关于组织的查询,以获取个人或其代理人可见的组织的所有后代?我知道 SQL,但总是无法使用 SelectManager 对组织进行自我加入。

4

3 回答 3

8

似乎没有任何答案的接受者,我自己找到了一种解决方法:

1.将最后一个连接转换为ActiveRecord::Relation

Organisation.where(o[:id].in(op))

唯一的问题是这个调用Arel::SelectManager.to_a带有一个弃用警告(也是一个昂贵的操作)。虽然我还没有找到替代方案(怀疑没有,这个弃用警告只是 Arel 中可观察到的不一致之一,它在 ActiveRecord 中被采用)。

2. 嵌套集合上的自连接获取所有后代

o = Organisation.scoped.table
op = Organisation.where(o[:person_id].in(Person.self_and_deputies(person_id).project(:id))).arel
o1 = Arel::Table.new(:organisations, :as => "o1")
o2 = Arel::Table.new(:organisations, :as => "o2")
o3 = o1.join(o2).on(
     o1[:lft].gteq(o2[:lft]).and(
     o1[:rgt].lteq(o2[:rgt]))).where(
     o2[:id].in(op)).project("distinct o1.id")
Organisation.where(o[:id].in(o3))
于 2010-12-23T20:26:50.933 回答
4

你也可以这样做:

Organisation.joins(op.join_sql).where(op.where_sql)

我也搜索了一段时间后得到了这个。这将允许您在其上堆叠任何其他范围。

于 2014-02-18T14:40:12.737 回答
4

您应该能够调用join_sources的实例Arel::SelectManager,该实例可以传递给ActiveRecord::Relation#joins. 您的查询将如下所示(未经测试):

o = Organisation.scoped.table
op = Organisation.where(o[:person_id].in(Person.self_and_deputies(person_id).project(:id))).arel
o1 = Arel::Table.new(:organisations, :as => "o1")
o2 = Arel::Table.new(:organisations, :as => "o2")
o3 = Organization.joins(
  o1.join(o2).
    on(o1[:lft].gteq(o2[:lft]).and(o1[:rgt].lteq(o2[:rgt]))).join_sources).
  where(o2[:id].in(op)).
  project("distinct o1.id")
于 2013-03-13T05:57:59.903 回答