【发布时间】:2018-06-22 14:59:54
【问题描述】:
给定以下模型
class Company < ApplicationRecord
has_many :employees, -> { order(rank: :asc)}
end
class Employee < ApplicationRecord
belongs_to :company
end
Rails 在使用 eager_load 构建查询时似乎忽略了默认排序,但在使用 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 甚至允许在关联的默认范围内指定顺序?如果抛出异常,几乎感觉会更好。
【问题讨论】:
-
说实话,即使我也有同感。关联应该保持简单。指定顺序或传递 lambda 以前所未有的方式修改了整个关联。如果需要所有这些修改,
scopes就足够了;在协会上堆积同样的东西似乎完全错误。
标签: sql ruby-on-rails activerecord