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

时间:2018-06-22 14:59:55

标签: sql ruby-on-rails activerecord

给出以下模型

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,则不一定会起作用(雇员将被排序,但是DB实施了默认排序)

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

1 个答案:

答案 0 :(得分:0)

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

因为Rails喜欢provide sharp knives

  

该框架提供的刀具远不及该语言提供的刀具锋利,但其中一些刀具仍很热切。对于为套件提供此类工具,我们不会道歉。实际上,我们应该庆祝对程序员的抱负有足够的信心,以敢于相信他们。

也许更确切地说,这似乎是一个永远为人所知且从未得到修复的错误,请参见:https://github.com/rails/rails/issues/6769