非确定性Rails关联默认顺序?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了非确定性Rails关联默认顺序?相关的知识,希望对你有一定的参考价值。

鉴于以下型号

class Company < ApplicationRecord
  has_many :employees, -> { order(rank: :asc)}
end

class Employee < ApplicationRecord
  belongs_to :company
end

在使用eager_load构建查询时,Rails似乎忽略了默认顺序,但在使用preload时包含它们...

Company.preload(:employees)
Company Load (0.3ms)  SELECT "companies".* FROM "companies"
Employee Load (0.3ms)  SELECT "employees".* FROM "employees" WHERE "employees"."company_id" = 1 ORDER BY "employees"."rank" ASC
=> [#<Company:0x00007f808c9e73c0 id: 1, name: "Acme Co">]

^^^注意ORDER BY employees.rank ASC的'正确'应用

Company.eager_load(:employees)
SQL (0.4ms)  SELECT "companies"."id" AS t0_r0, "companies"."name" AS t0_r1, "employees"."id" AS t1_r0, "employees"."name" AS t1_r1, "employees"."rank" AS t1_r2, "employees"."company_id" AS t1_r3 FROM "companies" LEFT OUTER JOIN "employees" ON "employees"."company_id" = "companies"."id"

^^^注意缺少任何类型的员工订购

(我想当你考虑它时就有意义了。如果你有多个关联被加入,所有都有自己的默认排序......那怎么会有效。我也认识到依赖于关联中的默认排序顺序是什么这个例子有点做作,而不是最佳实践,但在很多情况下,我可以看到这是一种有效的方法。)

当你做像Company.includes(:employees).first.employees.first.award_bonus这样的事情,假设这些员工按等级排序时,问题就出现了。如果Rails在包含员工时决定使用preload,那将会有效,但如果Rails决定使用eager_load则不一定会工作(但是,如果数据库执行它的默认排序,员工将被命令)

为什么Rails甚至允许在关联的默认范围内指定一个订单?如果抛出异常,几乎会感觉更好。

答案

为什么Rails甚至允许在关联的默认范围内指定一个订单?

因为Rails喜欢provide sharp knives

框架提供的刀具并不像语言提供的刀具那么尖锐,但有些刀具仍然非常热衷于削减。对于提供此类工具作为套件的一部分,我们不会道歉。事实上,我们应该庆祝对我们的程序员们的愿望有足够的信心,敢于信任他们。

也许更重要的是,这似乎是一个永远已知的错误,从未得到修复,请看这里:https://github.com/rails/rails/issues/6769

以上是关于非确定性Rails关联默认顺序?的主要内容,如果未能解决你的问题,请参考以下文章

在每个用户的Rails中使用片段缓存

不确定关联是不是在我的 rails 应用程序中有效

Rails:rails 模型的默认排序顺序?

如何在整个 Rails 活动记录关联链中取消特定模型的默认范围?

以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?

Rails 关联帮助 - 我是不是使用多态关联?