有没有办法取回 ActiveRecord::Relation 中的 where 条件?

问题描述 投票:0回答:1

如果我这样做:

rel = Foo.where(:foo_field => 123).joins(:bars).where(:bars => { :xyz => 123 });

有没有办法从该关系中获取条形条件

{ :xyz => 123 }

我看到我可以做

rel.where_clause.to_h
,但这给了我
{ :foo_field => 123, :xyz => 123 }
,并且没有办法区分专门用于酒吧加入的内容...有没有办法只返回酒吧条件?

activerecord arel
1个回答
0
投票

需要注意的是,可能有一种更简单的方法来完成您最终想要做的事情,您可以使用底层 Arel AST 中的信息来确定哪些 where 条件附加到哪个表。仅当它们以哈希形式指定时才有效 - 例如,Arel 不会解析文字 SQL 条件以了解它们涉及哪个表。

这是我想出的方法,使用递归方法进行深度优先搜索来识别我们感兴趣的表达式:

def collect_where_nodes(node, relation_name)
  if node.respond_to?(:eq) && node.respond_to?(:left) && node.left.respond_to?(:relation)
    node.left.relation.name == relation_name ? [node] : []
  elsif node.respond_to?(:children)
    node.children.flat_map { |c| collect_where_nodes(c, relation_name) }
  else
    []
  end
end

rel = Foo.where(:foo_field => 123).joins(:bars).where(:bars => { :xyz => 123 })

nodes = collect_where_nodes(rel.where_clause.ast, "bars")

但是,此函数的结果是

Arel::Node
,而不是像您原来的问题所要求的那样的简化哈希。简单的条件可以映射回哈希,但这并不适用于所有情况(例如,范围需要更多特殊处理):

hash = nodes.reduce({}) { |h, n| h.merge(n.left.name => n.right.value) }
© www.soinside.com 2019 - 2024. All rights reserved.