Rails 升级包括方法行为更改
Rails upgrade includes method behavior change
我已经研究了几天,但没有找到对这种行为变化的很好的解释。
我正在将 Rails 应用程序从 3.2 升级到 5.2
这是我的 rails 3 应用通过测试的代码。
ps = Project.includes(:rentals).where('rentals.id IN (?)', [1,2,3,4])
这会吐出一个大的旧左连接 SQL 查询。
但如果我在 rails 5 中执行相同的查询,我会收到 mysql 错误
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'rentals.id' in 'where clause': SELECT `projects`.* FROM `projects` WHERE (rentals.id IN (1,2,3,4)) LIMIT 11 /*application:ConHQ*/)
我对包含的理解是它应该执行单独的查询,除非在 where 子句中引用了包含的 table,在这种情况下它应该执行左连接。但似乎这并没有发生在这里。在这种情况下使用 eager_load 有效:
ps = Project.eager_load(:rentals).where('rentals.id IN (?)', [1,2,3,4])
但我认为包含应该做同样的事情。
我还注意到有时包含 does 执行与 eager_load
相同的查询
@project = Project.find(174)
@project.rentals.eager_load(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
@project.rentals.includes(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
在本例中 eager_load 和 includes 都执行左连接。我还没有找到任何文档来解释为什么 includes 在这些情况下会有不同的行为。 includes 究竟如何选择它执行的查询?
includes
只是告诉 ActiveRecord 应该预先加载数据,但它可以随心所欲地实现这一点。如果您想在查询中引用其他模型,您也必须使用 references(:rentals)
。
ActiveRecord API 非常强大且用途广泛,但与 Ruby 及其库一样,有很多方法可以实现某些目标。在这种情况下,您还可以使用 merge
合并到另一个关系中。
rentals = Rental.where(id: [1,2,3,4])
projects = Project.joins(:rentals).merge(rentals) # you can additionally add includes, too, if you want to access the rentals
这还有一个额外的好处,就是您无需关心 Rental
模型的 table 名称。
我已经研究了几天,但没有找到对这种行为变化的很好的解释。 我正在将 Rails 应用程序从 3.2 升级到 5.2 这是我的 rails 3 应用通过测试的代码。
ps = Project.includes(:rentals).where('rentals.id IN (?)', [1,2,3,4])
这会吐出一个大的旧左连接 SQL 查询。
但如果我在 rails 5 中执行相同的查询,我会收到 mysql 错误
ActiveRecord::StatementInvalid (Mysql2::Error: Unknown column 'rentals.id' in 'where clause': SELECT `projects`.* FROM `projects` WHERE (rentals.id IN (1,2,3,4)) LIMIT 11 /*application:ConHQ*/)
我对包含的理解是它应该执行单独的查询,除非在 where 子句中引用了包含的 table,在这种情况下它应该执行左连接。但似乎这并没有发生在这里。在这种情况下使用 eager_load 有效:
ps = Project.eager_load(:rentals).where('rentals.id IN (?)', [1,2,3,4])
但我认为包含应该做同样的事情。
我还注意到有时包含 does 执行与 eager_load
@project = Project.find(174)
@project.rentals.eager_load(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
@project.rentals.includes(:equipment_name).where('equipment_names.id IN (?)', [1,2,3,4])
在本例中 eager_load 和 includes 都执行左连接。我还没有找到任何文档来解释为什么 includes 在这些情况下会有不同的行为。 includes 究竟如何选择它执行的查询?
includes
只是告诉 ActiveRecord 应该预先加载数据,但它可以随心所欲地实现这一点。如果您想在查询中引用其他模型,您也必须使用 references(:rentals)
。
ActiveRecord API 非常强大且用途广泛,但与 Ruby 及其库一样,有很多方法可以实现某些目标。在这种情况下,您还可以使用 merge
合并到另一个关系中。
rentals = Rental.where(id: [1,2,3,4])
projects = Project.joins(:rentals).merge(rentals) # you can additionally add includes, too, if you want to access the rentals
这还有一个额外的好处,就是您无需关心 Rental
模型的 table 名称。