将Arel用于嵌套集合&;联接查询并转换为ActiveRecord::关系

将Arel用于嵌套集合&;联接查询并转换为ActiveRecord::关系,activerecord,ruby-on-rails-3,arel,Activerecord,Ruby On Rails 3,Arel,我有一个组织模型(嵌套集)。我为人们树立了一个榜样。一个人可以有另一个人作为代理人。一个组织由一个人拥有。一个组织只对拥有者或其副手可见 我希望检索给定人员可见的所有组织,即该人员拥有的所有组织或由人员拥有的所有组织(给定人员是其代理人): 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)

我有一个组织模型(嵌套集)。我为人们树立了一个榜样。一个人可以有另一个人作为代理人。一个组织由一个人拥有。一个组织只对拥有者或其副手可见

我希望检索给定人员可见的所有组织,即该人员拥有的所有组织或由人员拥有的所有组织(给定人员是其代理人):

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::Relationship,从而受益于“组合下的闭包”的整个概念


我如何再次加入上述关于组织的查询,以获得个人或其代理人可见的组织的所有后代?我知道SQL,但SelectManager在组织上进行自我加入时总是失败。

似乎没有人愿意接受任何答案,我自己也找到了解决方法:

一,。将最后一个联接转换为
ActiveRecord::Relation

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

二,。嵌套集上的自联接以获取所有子体


您应该能够调用
Arel::SelectManager
实例上的
join\u sources
,该实例可以传递到
ActiveRecord::Relation\joins
。您的查询如下(未测试):

你也可以这样做:

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

我也找了一段时间才得到这个。这将允许您在其上堆叠任何其他作用域。

因此,我想我有一个类似的问题,但在应用解决方案2时遇到困难:我找不到
。请再加入sql
。这个解决方案对我来说很有效,使Arel重新成为AR。这很有效。因此,一般的模式是:编写您的
Arel::SelectManager
,然后调用
。在其上加入源
,将其放入“可加入形式”,然后在其上加入。
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))
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")
Organisation.joins(op.join_sql).where(op.where_sql)