Return a null object from `AttributeSet#[]`

This commit is contained in:
Sean Griffin 2014-06-20 11:36:23 -06:00
parent 081eec4ba6
commit 6d7ac31ddb
6 changed files with 17 additions and 12 deletions

View File

@ -43,9 +43,7 @@ module ActiveRecord
# task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
# task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
def read_attribute_before_type_cast(attr_name)
if attr = @attributes[attr_name.to_s]
attr.value_before_type_cast
end
@attributes[attr_name.to_s].value_before_type_cast
end
# Returns a hash of attributes before typecasting and deserialization.

View File

@ -129,7 +129,7 @@ module ActiveRecord
end
def _field_changed?(attr, old_value)
attribute_named(attr).changed_from?(old_value)
@attributes[attr].changed_from?(old_value)
end
def changed_in_place
@ -140,7 +140,7 @@ module ActiveRecord
def changed_in_place?(attr_name)
old_value = original_raw_attribute(attr_name)
attribute_named(attr_name).changed_in_place_from?(old_value)
@attributes[attr_name].changed_in_place_from?(old_value)
end
def original_raw_attribute(attr_name)
@ -154,7 +154,7 @@ module ActiveRecord
end
def store_original_raw_attribute(attr_name)
original_raw_attributes[attr_name] = attribute_named(attr_name).value_for_database
original_raw_attributes[attr_name] = @attributes[attr_name].value_for_database
end
def store_original_raw_attributes

View File

@ -99,10 +99,6 @@ module ActiveRecord
def attribute(attribute_name)
read_attribute(attribute_name)
end
def attribute_named(attribute_name)
@attributes.fetch(attribute_name, Attribute::Null)
end
end
end
end

View File

@ -35,7 +35,8 @@ module ActiveRecord
end
def build_from_database(values, additional_types = {})
attributes = values.each_with_object({}) do |(name, value), hash|
attributes = Hash.new(Attribute::Null)
values.each_with_object(attributes) do |(name, value), hash|
type = additional_types.fetch(name, @types[name])
hash[name] = Attribute.from_database(value, type)
end

View File

@ -523,7 +523,9 @@ module ActiveRecord
def init_internals
pk = self.class.primary_key
@attributes[pk] ||= Attribute.from_database(nil, type_for_attribute(pk))
unless @attributes.include?(pk)
@attributes[pk] = Attribute.from_database(nil, type_for_attribute(pk))
end
@aggregation_cache = {}
@association_cache = {}

View File

@ -18,6 +18,14 @@ module ActiveRecord
assert_equal 4, attributes[:bar].value
end
test "[] returns a null object" do
builder = AttributeSet::Builder.new(foo: Type::Float.new)
attributes = builder.build_from_database(foo: '3.3')
assert_equal '3.3', attributes[:foo].value_before_type_cast
assert_equal nil, attributes[:bar].value_before_type_cast
end
test "duping creates a new hash and dups each attribute" do
builder = AttributeSet::Builder.new(foo: Type::Integer.new, bar: Type::String.new)
attributes = builder.build_from_database(foo: 1, bar: 'foo')