Maintain a consistent order in `ActiveRecord::Base#attributes`

Fixes #18871
This commit is contained in:
Sean Griffin 2015-02-10 08:20:54 -07:00
parent d89912b9be
commit 2f8c596d1b
2 changed files with 21 additions and 1 deletions

View File

@ -20,7 +20,7 @@ module ActiveRecord
end
class LazyAttributeHash # :nodoc:
delegate :select, :transform_values, :each_key, to: :materialize
delegate :transform_values, :each_key, to: :materialize
def initialize(types, values, additional_types)
@types = types
@ -50,6 +50,16 @@ module ActiveRecord
super
end
def select
keys = types.keys | values.keys | delegate_hash.keys
keys.each_with_object({}) do |key, hash|
attribute = self[key]
if yield(key, attribute)
hash[key] = attribute
end
end
end
protected
attr_reader :types, :values, :additional_types, :delegate_hash

View File

@ -65,6 +65,16 @@ module ActiveRecord
assert_equal({ foo: 1, bar: 2.2 }, attributes.to_h)
end
test "to_hash maintains order" do
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Float.new)
attributes = builder.build_from_database(foo: '2.2', bar: '3.3')
attributes[:bar]
hash = attributes.to_h
assert_equal [[:foo, 2], [:bar, 3.3]], hash.to_a
end
test "values_before_type_cast" do
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::Integer.new)
attributes = builder.build_from_database(foo: '1.1', bar: '2.2')