如何从现有 ActiveRecord_Relation 中获取 where 表达式中使用的列?
How can I get the columns used in the where expression from an existing ActiveRecord_Relation?
说我的很多模型都实现了 class 方法 self.foo 其中 returns a ::ActiveRecord_Relation.
从代码的其他地方,我可以访问该方法返回的模型或 ::ActiveRecord_Relation,我想找出查询中的 where 表达式中使用了哪些列。
如果查询很简单,我可以从 ActiveRecord_Relation 上的 where_values_hash 获取它,但我无法弄清楚如何在更复杂的查询中获取所有列。
class A < ApplicationRecord
def self.foo(bar)
where(column1: bar)
end
end
class B < ApplicationRecord
def self.foo(bar)
joins(:c).
merge(C.where(column2: bar))
end
end
别处
# this evaluates to ["column1"] - success!
A.foo(bar).where_values_hash.keys
# How can I get "c" or C and "column2" from B or B.foo(bar)?
# B or B.foo(bar).??? -> ["c", "column2"]
我总能从解析关系的 .to_sql 字符串中得到它,但必须有更好的方法。
where_values_hash 方法采用一个参数,该参数是您想要 where 子句列的 table。如果你想要所有这些,你可以用 Arel 做一些事情来获得所有加入的 tables where_values_hash。唯一的技巧是您可能希望保留 table 列来自的上下文。
def join_where_values(relation)
relation.arel.join_sources.map do |r|
{ r.left.name => relation.where_values_hash(r.left.name) }
end
end
{ 'b' => B.foo(bar).where_values_hash, 'joins' => join_where_values(B.foo(bar)) }
说我的很多模型都实现了 class 方法 self.foo 其中 returns a ::ActiveRecord_Relation.
从代码的其他地方,我可以访问该方法返回的模型或 ::ActiveRecord_Relation,我想找出查询中的 where 表达式中使用了哪些列。
如果查询很简单,我可以从 ActiveRecord_Relation 上的 where_values_hash 获取它,但我无法弄清楚如何在更复杂的查询中获取所有列。
class A < ApplicationRecord
def self.foo(bar)
where(column1: bar)
end
end
class B < ApplicationRecord
def self.foo(bar)
joins(:c).
merge(C.where(column2: bar))
end
end
别处
# this evaluates to ["column1"] - success!
A.foo(bar).where_values_hash.keys
# How can I get "c" or C and "column2" from B or B.foo(bar)?
# B or B.foo(bar).??? -> ["c", "column2"]
我总能从解析关系的 .to_sql 字符串中得到它,但必须有更好的方法。
where_values_hash 方法采用一个参数,该参数是您想要 where 子句列的 table。如果你想要所有这些,你可以用 Arel 做一些事情来获得所有加入的 tables where_values_hash。唯一的技巧是您可能希望保留 table 列来自的上下文。
def join_where_values(relation)
relation.arel.join_sources.map do |r|
{ r.left.name => relation.where_values_hash(r.left.name) }
end
end
{ 'b' => B.foo(bar).where_values_hash, 'joins' => join_where_values(B.foo(bar)) }