Reputation: 317
Given the following models
class Company < ApplicationRecord
has_many :employees, -> { order(rank: :asc)}
end
class Employee < ApplicationRecord
belongs_to :company
end
Rails seems to ignore the default ordering when building queries with eager_load
but includes them when using 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">]
^^^ Note the 'correct' application of 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"
^^^ Note the lack of any kind of employee ordering
(I guess that makes sense when you think about it. What if you have multiple associations being joined in, all with their own default ordering...how would that even work. I also recognize relying on a default sort order in the association is a bit contrived and not best practice with this example, but there are many scenarios where I could see that being a valid approach.)
The problem seems to arise when you do something like Company.includes(:employees).first.employees.first.award_bonus
assuming those employees are ordered by rank. That will work if Rails decides to use preload
when including employees, but will not necessarily work if Rails decides to use eager_load
(employees would be ordered by however the DB implements it's default sorting)
Why does Rails even allow specifying an order in an association's default scope? It would almost feel better if an exception was thrown.
Upvotes: 4
Views: 693
Reputation: 830
Why does Rails even allow specifying an order in an association's default scope?
Because Rails likes to provide sharp knives.
The knives provided by the framework are not nearly as sharp as those offered with the language, but some are still plenty keen to cut. We will make no apologies for offering such tools as part of the kit. In fact, we should celebrate having enough faith in the aspirations of our fellow programmers to dare trust them.
Maybe more to your point though, this appears to be a bug that has been known about forever and has never gotten fixed, see here: https://github.com/rails/rails/issues/6769
Upvotes: 1