Fix `QueryMethods#in_order_of` to handle empty order list

Fix: https://github.com/rails/rails/issues/43903
Ref: https://github.com/rails/rails/pull/42061

Simply don't generate the case statement if the order list is empty
and fallback to default ordering.
This commit is contained in:
Jean Boussier 2021-12-17 14:25:48 +01:00
parent b376da83b3
commit fb77d4a39d
3 changed files with 30 additions and 3 deletions

View File

@ -1,3 +1,14 @@
* Fix `QueryMethods#in_order_of` to handle empty order list.
```ruby
Post.in_order_of(:id, []).to_a
```
Also more explicitly set the column as secondary order, so that any other
value is still ordered.
*Jean Boussier*
* Fix quoting of column aliases generated by calculation methods. * Fix quoting of column aliases generated by calculation methods.
Since the alias is derived from the table name, we can't assume the result Since the alias is derived from the table name, we can't assume the result

View File

@ -432,10 +432,14 @@ module ActiveRecord
references = column_references([column]) references = column_references([column])
self.references_values |= references unless references.empty? self.references_values |= references unless references.empty?
if values.empty?
spawn.order!(column)
else
values = values.map { |value| type_caster.type_cast_for_database(column, value) } values = values.map { |value| type_caster.type_cast_for_database(column, value) }
column = order_column(column.to_s) if column.is_a?(Symbol)
spawn.order!(connection.field_ordered_value(column, values)) arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
spawn.order!(connection.field_ordered_value(arel_column, values), column)
end
end end
# Replaces any existing order defined on the relation with the specified order. # Replaces any existing order defined on the relation with the specified order.

View File

@ -14,6 +14,18 @@ class FieldOrderedValuesTest < ActiveRecord::TestCase
assert_equal(order, posts.map(&:id)) assert_equal(order, posts.map(&:id))
end end
def test_unspecified_order
order = [3, 4, 1]
post_ids = Post.in_order_of(:id, order).map(&:id)
expected_order = order + (post_ids - order).sort
assert_equal(expected_order, post_ids)
end
def test_in_order_of_empty
posts = Post.in_order_of(:id, [])
assert_equal(posts.map(&:id).sort, posts.map(&:id))
end
def test_in_order_of_with_enums_values def test_in_order_of_with_enums_values
Book.destroy_all Book.destroy_all
Book.create!(status: :proposed) Book.create!(status: :proposed)