diff options
-rw-r--r-- | activemodel/lib/active_model/attribute_set.rb | 2 | ||||
-rw-r--r-- | activemodel/lib/active_model/attribute_set/builder.rb | 28 | ||||
-rw-r--r-- | activemodel/test/cases/attribute_set_test.rb | 3 | ||||
-rw-r--r-- | activerecord/lib/active_record/model_schema.rb | 8 |
4 files changed, 21 insertions, 20 deletions
diff --git a/activemodel/lib/active_model/attribute_set.rb b/activemodel/lib/active_model/attribute_set.rb index a892accbc6..54a5dd4064 100644 --- a/activemodel/lib/active_model/attribute_set.rb +++ b/activemodel/lib/active_model/attribute_set.rb @@ -5,7 +5,7 @@ require "active_model/attribute_set/yaml_encoder" module ActiveModel class AttributeSet # :nodoc: - delegate :each_value, :fetch, to: :attributes + delegate :each_value, :fetch, :except, to: :attributes def initialize(attributes) @attributes = attributes diff --git a/activemodel/lib/active_model/attribute_set/builder.rb b/activemodel/lib/active_model/attribute_set/builder.rb index f94f47370f..758eb830fc 100644 --- a/activemodel/lib/active_model/attribute_set/builder.rb +++ b/activemodel/lib/active_model/attribute_set/builder.rb @@ -5,35 +5,30 @@ require "active_model/attribute" module ActiveModel class AttributeSet # :nodoc: class Builder # :nodoc: - attr_reader :types, :always_initialized, :default + attr_reader :types, :default_attributes - def initialize(types, always_initialized = nil, &default) + def initialize(types, default_attributes = {}) @types = types - @always_initialized = always_initialized - @default = default + @default_attributes = default_attributes end def build_from_database(values = {}, additional_types = {}) - if always_initialized && !values.key?(always_initialized) - values[always_initialized] = nil - end - - attributes = LazyAttributeHash.new(types, values, additional_types, &default) + attributes = LazyAttributeHash.new(types, values, additional_types, default_attributes) AttributeSet.new(attributes) end end end class LazyAttributeHash # :nodoc: - delegate :transform_values, :each_key, :each_value, :fetch, to: :materialize + delegate :transform_values, :each_key, :each_value, :fetch, :except, to: :materialize - def initialize(types, values, additional_types, &default) + def initialize(types, values, additional_types, default_attributes) @types = types @values = values @additional_types = additional_types @materialized = false @delegate_hash = {} - @default = default || proc {} + @default_attributes = default_attributes end def key?(key) @@ -94,7 +89,7 @@ module ActiveModel protected - attr_reader :types, :values, :additional_types, :delegate_hash, :default + attr_reader :types, :values, :additional_types, :delegate_hash, :default_attributes def materialize unless @materialized @@ -117,7 +112,12 @@ module ActiveModel if value_present delegate_hash[name] = Attribute.from_database(name, value, type) elsif types.key?(name) - delegate_hash[name] = default.call(name) || Attribute.uninitialized(name, type) + attr = default_attributes[name] + if attr + delegate_hash[name] = attr.dup + else + delegate_hash[name] = Attribute.uninitialized(name, type) + end end end end diff --git a/activemodel/test/cases/attribute_set_test.rb b/activemodel/test/cases/attribute_set_test.rb index 02c44c5d45..6e522d6c80 100644 --- a/activemodel/test/cases/attribute_set_test.rb +++ b/activemodel/test/cases/attribute_set_test.rb @@ -163,7 +163,8 @@ module ActiveModel end test "the primary_key is always initialized" do - builder = AttributeSet::Builder.new({ foo: Type::Integer.new }, :foo) + defaults = { foo: Attribute.from_user(:foo, nil, nil) } + builder = AttributeSet::Builder.new({ foo: Type::Integer.new }, defaults) attributes = builder.build_from_database assert attributes.key?(:foo) diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 12ee4a4137..1941d3d5ea 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -323,11 +323,11 @@ module ActiveRecord end def attributes_builder # :nodoc: - @attributes_builder ||= ActiveModel::AttributeSet::Builder.new(attribute_types, primary_key) do |name| - unless columns_hash.key?(name) - _default_attributes[name].dup - end + unless defined?(@attributes_builder) && @attributes_builder + defaults = _default_attributes.except(*(column_names - [primary_key])) + @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults) end + @attributes_builder end def columns_hash # :nodoc: |