5

我有这个用例,我从某个模型中获取符号化的深度关联,并且我必须执行某些涉及使用外连接的查询。如果不手动编写完整的 SQL,怎么能做到这一点?

我不想要的答案: - 使用包含(不能很好地解决深层关联( .includes(:cars => [:windows, :engine => [:ignition]..... 出乎意料地工作)我不'不想要它的副作用) - 自己编写 SQL(对不起,它是 2013 年,跨数据库支持等等等......,我获取的对象是只读的,更多的副作用)

我想要一个 Arel 解决方案。我知道使用模型中的 arel_table 可以构造 SQL 表达式,还有一个用于连接的 DSL,但不知何故我不能在模型的连接方法中使用它:

car = Car.arel_table
engine = Engine.arel_table

eng_exp = car.join(engine).on(car[:engine_id].eq(engine[:id]))
eng_exp.to_sql #=> GOOD! very nice!
Car.joins(eng_exp) #=> Breaks!!

为什么这不起作用超出了我的范围。我不知道究竟缺少什么。但这是我现在拥有的最接近解决方案的东西。如果有人可以帮助我完成我的示例或为我提供一个很好的解决方法或告诉我 Rails 何时会包含如此明显必要的功能,我将永远感激不尽。

4

3 回答 3

9

这是一个古老的问题,但为了任何通过搜索引擎找到它的人的利益:

如果你想要一些你可以传入的东西.joins,你可以使用.create_joinand .create_on

join_on = car.create_on(car[:engine_id].eq(engine[:id]))
eng_join = car.create_join(engine, join_on, Arel::Nodes::OuterJoin)

Car.joins(eng_join)

或者

使用.join_sources来自您构造的连接对象:

eng_exp = car.join(engine, Arel::Nodes::OuterJoin).on(car[:engine_id].eq(engine[:id]))
Car.joins(eng_exp.join_sources)
于 2014-03-04T10:29:37.773 回答
7

我发现了一篇旨在解决此问题的博客文章:http ://blog.donwilson.net/2011/11/constructing-a-less-than-simple-query-with-rails-and-arel/

基于此(以及我自己的测试),以下内容应该适用于您的情况:

car = Car.arel_table
engine = Engine.arel_table   

sql = car.project(car[Arel.star])
        .join(engine, Arel::Nodes::OuterJoin).on(car[:engine_id].eq(engine[:id]))

Car.find_by_sql(sql)
于 2013-02-22T20:05:42.147 回答
0

如果您不介意添加依赖项并完全跳过 AREL,您可以使用Ernie Miller 出色的 Squeel gem。会是这样的

Car.joins{engine.outer}.where(...)

这将要求 Car 模型与 Engine 相关联,如下所示:

belongs_to :engine
于 2015-07-31T21:39:14.970 回答