1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

QueryMethods#in_order_of drop records not listed

`in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.

*Kevin Newton*
This commit is contained in:
Kevin Newton 2022-01-06 12:54:41 -05:00
parent 6fb54c00e4
commit e7c3219cb5
No known key found for this signature in database
GPG key ID: FBE789CDA03B16F6
3 changed files with 20 additions and 19 deletions

View file

@ -1,3 +1,9 @@
* Change `QueryMethods#in_order_of` to drop records not listed in values.
`in_order_of` now filters down to the values provided, to match the behavior of the `Enumerable` version.
*Kevin Newton*
* Allow named expression indexes to be revertible.
Previously, the following code would raise an error in a reversible migration executed while rolling back, due to the index name not being used in the index removal.

View file

@ -432,22 +432,23 @@ module ActiveRecord
# adapter this will either use a CASE statement or a built-in function.
#
# User.in_order_of(:id, [1, 5, 3])
# # SELECT "users".* FROM "users" ORDER BY FIELD("users"."id", 1, 5, 3)
# # SELECT "users".* FROM "users"
# # ORDER BY FIELD("users"."id", 1, 5, 3)
# # WHERE "users"."id" IN (1, 5, 3)
#
def in_order_of(column, values)
klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
return spawn.none! if values.empty?
references = column_references([column])
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) }
arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
spawn.order!(connection.field_ordered_value(arel_column, values), column)
end
spawn
.order!(connection.field_ordered_value(arel_column, values))
.where!(arel_column.in(values))
end
# Replaces any existing order defined on the relation with the specified order.

View file

@ -9,21 +9,15 @@ class FieldOrderedValuesTest < ActiveRecord::TestCase
def test_in_order_of
order = [3, 4, 1]
posts = Post.in_order_of(:id, order).limit(3)
posts = Post.in_order_of(:id, order)
assert_equal(order, posts.map(&:id))
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))
assert_empty(posts)
end
def test_in_order_of_with_enums_values
@ -52,14 +46,14 @@ class FieldOrderedValuesTest < ActiveRecord::TestCase
def test_in_order_of_expression
order = [3, 4, 1]
posts = Post.in_order_of(Arel.sql("id * 2"), order.map { |id| id * 2 }).limit(3)
posts = Post.in_order_of(Arel.sql("id * 2"), order.map { |id| id * 2 })
assert_equal(order, posts.map(&:id))
end
def test_in_order_of_after_regular_order
order = [3, 4, 1]
posts = Post.where(type: "Post").order(:type).in_order_of(:id, order).limit(3)
posts = Post.where(type: "Post").order(:type).in_order_of(:id, order)
assert_equal(order, posts.map(&:id))
end