Rails ActiveRecord:动态构建查询

28
我试图组合一系列的类,可以使用ActiveRecord动态地创建和执行复杂查询。我对这个做法感到非常舒适:
MyModel.select("id, name, floober").join(:creator).where(:is_active => true)
我在使用这些东西构建查询时遇到了困难,因为我无法确定每个可能的方法(连接数、where子句数、限制、组等)将有多少个,事先是无法确定的。有时候调用它时需要2个连接,有时不需要。

由于我获取这些内容的方式的特殊性--一个连接列表,一个列列表,一个where子句列表等,我可以盲目地将它们链接在一起。我必须将列连接在一起,排列连接,链接where子句,所以我不能循环遍历各种列表。

我试过的一件事是将Ruby语句构建为字符串,然后在最后评估它,但完成后感觉很肮脏,就像需要洗个澡一样。我正在寻找一种方式来缓存我的查询状态,直到所有部分都累积完毕,然后再执行它们。

我走"off the Rails"了吗?

提前感谢...

2个回答

63

我想我明白了。我对AR查询方法的理解相当偏离轨道。事实证明,ActiveRecord直到你尝试使用结果时才会真正执行查询。因此,可以做出以下操作:

model_query = MyModel.select("column12, column32")
model_query = model_query.joins(:user)
model_query = model_query.where(:column12 => true)

然后在所有的东西都建好之后,您可以执行

model_query.each do |record|
  ...
end

直到你调用each方法(或者其他需要查询结果的方法)查询才会被真正执行。

我从观看 Railscasts 202215 得到了这个信息。我很喜欢 Ryan Bates。


1
谢谢这个 - 我一直在想是否可以像这样逐步构建查询,或者它会导致运行多个 SQL 查询。 - tomato
我必须补充说明的是,这个功能在Rails 2中也可以使用;你可以像这样组合named_scope,它们会被链接并且只在需要时执行。 - pierallard
这对我没用...在Rails 3.2.13中是否可用?? - shajin
1
对于这个可能还感兴趣的人,也可以关注has_scope - Jason Swett
3
那些说它对他们不起作用的人...你是否试图在Rails控制台中尝试此操作?在3.x版本中,Rails控制台经常强制解释AR,因为它使用某种形式的I/O评估来在下一行显示值。在4.2版中,语法可能略有改变。但我向你保证,这确实有效--自3.0以来,我一直在使用它,并且目前正在同时使用4.2和5.0版本。 - user483040
十年后,Ryan Bates 对于 Railscasts 仍然是一个英雄。 - user137717

0
在这种情况下,send 可能是你的朋友。虽然代码执行仍然相当任意,但至少你没有使用 eval。不完全清楚你是否一次性拥有所有这些查询部分,还是随着时间的推移逐步构建它们。如果它们存在于一个 HTTP 请求/响应周期中,那么遍历查询部分并根据需要进行 send 是有意义的。
另一方面,如果你是通过 Ajax 或其他某种累积条件的方式获取它,你可能需要考虑缓存现有部分或一些更奇特的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接