Enumerable#in_order_of (#41333)
* Add Enumerable#in_order_of * Explain behavior further * Use Enumerable#in_order_of * Use Ruby 2.7 #filter_map * Update activesupport/lib/active_support/core_ext/enumerable.rb Co-authored-by: Jonathan Hefner <jonathan@hefner.pro> * No need for explaining variable * Add CHANGELOG entry Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
This commit is contained in:
parent
9e8824036d
commit
9cb09411e1
|
@ -520,10 +520,7 @@ module ActiveRecord
|
||||||
result = except(:limit, :offset).where(primary_key => ids).records
|
result = except(:limit, :offset).where(primary_key => ids).records
|
||||||
|
|
||||||
if result.size == ids.size
|
if result.size == ids.size
|
||||||
pk_type = @klass.type_for_attribute(primary_key)
|
result.in_order_of(:id, ids.map { |id| @klass.type_for_attribute(primary_key).cast(id) })
|
||||||
|
|
||||||
records_by_id = result.index_by(&:id)
|
|
||||||
ids.map { |id| records_by_id.fetch(pk_type.cast(id)) }
|
|
||||||
else
|
else
|
||||||
raise_record_not_found_exception!(ids, result.size, ids.size)
|
raise_record_not_found_exception!(ids, result.size, ids.size)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
* Add `Enumerable#in_order_of` to put an Enumerable in a certain order by a key.
|
||||||
|
|
||||||
|
*DHH*
|
||||||
|
|
||||||
* `ActiveSupport::Inflector.camelize` behaves expected when provided a symbol `:upper` or `:lower` argument. Matches
|
* `ActiveSupport::Inflector.camelize` behaves expected when provided a symbol `:upper` or `:lower` argument. Matches
|
||||||
`String#camelize` behavior.
|
`String#camelize` behavior.
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,18 @@ module Enumerable
|
||||||
def compact_blank
|
def compact_blank
|
||||||
reject(&:blank?)
|
reject(&:blank?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns a new +Array+ where the order has been set to that provided in the +series+, based on the +key+ of the
|
||||||
|
# objects in the original enumerable.
|
||||||
|
#
|
||||||
|
# [ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
|
||||||
|
# => [ Person.find(1), Person.find(5), Person.find(3) ]
|
||||||
|
#
|
||||||
|
# If the +series+ include keys that have no corresponding element in the Enumerable, these are ignored.
|
||||||
|
# If the Enumerable has additional elements that aren't named in the +series+, these are not included in the result.
|
||||||
|
def in_order_of(key, series)
|
||||||
|
index_by(&key).values_at(*series).compact
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Hash
|
class Hash
|
||||||
|
|
|
@ -284,4 +284,19 @@ class EnumerableTests < ActiveSupport::TestCase
|
||||||
values.compact_blank!
|
values.compact_blank!
|
||||||
assert_equal({ b: 1, f: true }, values)
|
assert_equal({ b: 1, f: true }, values)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_in_order_of
|
||||||
|
values = [ Payment.new(5), Payment.new(1), Payment.new(3) ]
|
||||||
|
assert_equal [ Payment.new(1), Payment.new(5), Payment.new(3) ], values.in_order_of(:price, [ 1, 5, 3 ])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_in_order_of_ignores_missing_series
|
||||||
|
values = [ Payment.new(5), Payment.new(1), Payment.new(3) ]
|
||||||
|
assert_equal [ Payment.new(1), Payment.new(5), Payment.new(3) ], values.in_order_of(:price, [ 1, 2, 4, 5, 3 ])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_in_order_of_drops_elements_not_named_in_series
|
||||||
|
values = [ Payment.new(5), Payment.new(1), Payment.new(3) ]
|
||||||
|
assert_equal [ Payment.new(1), Payment.new(5) ], values.in_order_of(:price, [ 1, 5 ])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue