From 895a53e7161e9bdc6285fe03f16b49ec74972416 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Fri, 14 Nov 2014 12:02:05 -0700 Subject: Allow `LazyAttributeHash` to be marshalled `default_proc` makes a hash unmarshallable, and adds unneccessary overhead. Since we control all access to the hash, let's just handle it in that method. This has the side effect of improving performance on initialization (but not neccessarily on access). We'll need to profile further once the tests are passing. --- .../lib/active_record/attribute_set/builder.rb | 30 ++++++++++++---------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb index 54e9cbb779..4134032659 100644 --- a/activerecord/lib/active_record/attribute_set/builder.rb +++ b/activerecord/lib/active_record/attribute_set/builder.rb @@ -23,7 +23,7 @@ module ActiveRecord class LazyAttributeHash delegate :select, :transform_values, to: :materialize - delegate :[], :[]=, :freeze, to: :delegate_hash + delegate :[]=, :freeze, to: :delegate_hash def initialize(types, values, additional_types) @types = types @@ -31,20 +31,26 @@ module ActiveRecord @additional_types = additional_types @materialized = false @delegate_hash = {} - assign_default_proc end def key?(key) delegate_hash.key?(key) || values.key?(key) || types.key?(key) end + def [](key) + if delegate_hash.key?(key) + delegate_hash[key] + else + assign_default_value(key) + end + end + def initialized_keys delegate_hash.keys | values.keys end def initialize_dup(_) @delegate_hash = delegate_hash.transform_values(&:dup) - assign_default_proc super end @@ -59,22 +65,20 @@ module ActiveRecord private - def assign_default_proc - delegate_hash.default_proc = proc do |hash, name| - type = additional_types.fetch(name, types[name]) + def assign_default_value(name) + type = additional_types.fetch(name, types[name]) - if values.key?(name) - hash[name] = Attribute.from_database(name, values[name], type) - elsif types.key?(name) - hash[name] = Attribute.uninitialized(name, type) - end + if values.key?(name) + delegate_hash[name] = Attribute.from_database(name, values[name], type) + elsif types.key?(name) + delegate_hash[name] = Attribute.uninitialized(name, type) end end def materialize unless @materialized - values.each_key { |key| delegate_hash[key] } - types.each_key { |key| delegate_hash[key] } + values.each_key { |key| self[key] } + types.each_key { |key| self[key] } @materialized = true end delegate_hash -- cgit v1.2.3