From bb7bc499e5f3355eee7955c4a2db7a9ee731bef4 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Sun, 22 Jun 2014 16:57:40 -0600 Subject: `Attribute` should know about its name This allows using polymorphism for the uninitialized attributes raising an exception behavior. --- activerecord/lib/active_record/attribute.rb | 47 +++++++++++++--------- activerecord/lib/active_record/attribute_set.rb | 14 +++---- .../lib/active_record/attribute_set/builder.rb | 7 ++-- 3 files changed, 36 insertions(+), 32 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb index 13c8bc3676..33c20bb5cc 100644 --- a/activerecord/lib/active_record/attribute.rb +++ b/activerecord/lib/active_record/attribute.rb @@ -1,24 +1,29 @@ module ActiveRecord class Attribute # :nodoc: class << self - def from_database(value, type) - FromDatabase.new(value, type) + def from_database(name, value, type) + FromDatabase.new(name, value, type) end - def from_user(value, type) - FromUser.new(value, type) + def from_user(name, value, type) + FromUser.new(name, value, type) end - def uninitialized(type) - Uninitialized.new(type) + def null(name) + Null.new(name) + end + + def uninitialized(name, type) + Uninitialized.new(name, type) end end - attr_reader :value_before_type_cast, :type + attr_reader :name, :value_before_type_cast, :type # This method should not be called directly. # Use #from_database or #from_user - def initialize(value_before_type_cast, type) + def initialize(name, value_before_type_cast, type) + @name = name @value_before_type_cast = value_before_type_cast @type = type end @@ -42,11 +47,11 @@ module ActiveRecord end def with_value_from_user(value) - self.class.from_user(value, type) + self.class.from_user(name, value, type) end def with_value_from_database(value) - self.class.from_database(value, type) + self.class.from_database(name, value, type) end def type_cast @@ -77,9 +82,9 @@ module ActiveRecord end end - class NullAttribute < Attribute # :nodoc: - def initialize - super(nil, Type::Value.new) + class Null < Attribute # :nodoc: + def initialize(name) + super(name, nil, Type::Value.new) end def value @@ -88,21 +93,23 @@ module ActiveRecord end class Uninitialized < Attribute # :nodoc: - def initialize(type) - super(nil, type) + def initialize(name, type) + super(name, nil, type) end def value - nil + if block_given? + yield name + end + end + + def value_for_database end - alias value_for_database value def initialized? false end end - private_constant :FromDatabase, :FromUser, :NullAttribute, :Uninitialized - - Null = NullAttribute.new # :nodoc: + private_constant :FromDatabase, :FromUser, :Null, :Uninitialized end end diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb index 65e15b16dd..5be11e6ab9 100644 --- a/activerecord/lib/active_record/attribute_set.rb +++ b/activerecord/lib/active_record/attribute_set.rb @@ -2,13 +2,16 @@ require 'active_record/attribute_set/builder' module ActiveRecord class AttributeSet # :nodoc: - delegate :[], to: :attributes delegate :keys, to: :initialized_attributes def initialize(attributes) @attributes = attributes end + def [](name) + attributes[name] || Attribute.null(name) + end + def values_before_type_cast attributes.each_with_object({}) { |(k, v), h| h[k] = v.value_before_type_cast } end @@ -22,13 +25,8 @@ module ActiveRecord attributes.include?(name) && self[name].initialized? end - def fetch_value(name) - attribute = self[name] - if attribute.initialized? || !block_given? - attribute.value - else - yield name - end + def fetch_value(name, &block) + self[name].value(&block) end def write_from_database(name, value) diff --git a/activerecord/lib/active_record/attribute_set/builder.rb b/activerecord/lib/active_record/attribute_set/builder.rb index f9cf9c1809..1e146a07da 100644 --- a/activerecord/lib/active_record/attribute_set/builder.rb +++ b/activerecord/lib/active_record/attribute_set/builder.rb @@ -16,16 +16,15 @@ module ActiveRecord private def build_attributes_from_values(values, additional_types) - attributes = Hash.new(Attribute::Null) - values.each_with_object(attributes) do |(name, value), hash| + values.each_with_object({}) do |(name, value), hash| type = additional_types.fetch(name, types[name]) - hash[name] = Attribute.from_database(value, type) + hash[name] = Attribute.from_database(name, value, type) end end def add_uninitialized_attributes(attributes) types.except(*attributes.keys).each do |name, type| - attributes[name] = Attribute.uninitialized(type) + attributes[name] = Attribute.uninitialized(name, type) end end end -- cgit v1.2.3