diff options
author | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-06-03 19:30:34 -0300 |
---|---|---|
committer | Rafael Mendonça França <rafaelmfranca@gmail.com> | 2014-06-03 19:30:34 -0300 |
commit | 1c6bb0efe0933cf0880c13ac0c379b65781a2353 (patch) | |
tree | 596553b7e8f59247b0ed7c53020a1b6aeaeb1720 /activerecord | |
parent | 18d19bf2a418f4e310e7792db6d8600c25f8b1b3 (diff) | |
parent | fb2a1c4b47800d6ed65662bed26fcdae66de5869 (diff) | |
download | rails-1c6bb0efe0933cf0880c13ac0c379b65781a2353.tar.gz rails-1c6bb0efe0933cf0880c13ac0c379b65781a2353.tar.bz2 rails-1c6bb0efe0933cf0880c13ac0c379b65781a2353.zip |
Merge pull request #15438 from sgrif/sg-null-column
Return a null column when no column exists for an attribute
Conflicts:
activerecord/CHANGELOG.md
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods.rb | 16 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/dirty.rb | 3 | ||||
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/write.rb | 12 | ||||
-rw-r--r-- | activerecord/test/cases/reflection_test.rb | 19 |
5 files changed, 40 insertions, 14 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 3adf7d70be..7ea3bde2bc 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,7 @@ +* Return a null column from `column_for_attribute` when no column exists. + + *Sean Griffin* + * Implemented ActiveRecord::Base#pretty_print to work with PP. *Ethan* diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index b6520b9b3d..e56a4cc805 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -350,10 +350,12 @@ module ActiveRecord # # => #<ActiveRecord::ConnectionAdapters::SQLite3Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...> # # person.column_for_attribute(:nothing) - # # => nil + # # => #<ActiveRecord::ConnectionAdapters::Column:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...> def column_for_attribute(name) - # FIXME: should this return a null object for columns that don't exist? - self.class.columns_hash[name.to_s] + name = name.to_s + self.class.columns_hash.fetch(name) do + ConnectionAdapters::Column.new(name, nil, Type::Value.new) + end end # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, @@ -438,16 +440,16 @@ module ActiveRecord # Filters the primary keys and readonly attributes from the attribute names. def attributes_for_update(attribute_names) - attribute_names.select do |name| - column_for_attribute(name) && !readonly_attribute?(name) + attribute_names.reject do |name| + readonly_attribute?(name) end end # Filters out the primary keys, from the attribute names, when the primary # key is to be generated (e.g. the id attribute has no value). def attributes_for_create(attribute_names) - attribute_names.select do |name| - column_for_attribute(name) && !(pk_attribute?(name) && id.nil?) + attribute_names.reject do |name| + pk_attribute?(name) && id.nil? end end diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 6cd4e43ddd..4e32b78e34 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -94,8 +94,7 @@ module ActiveRecord end def _field_changed?(attr, old, value) - column = column_for_attribute(attr) || Type::Value.new - column.changed?(old, value) + column_for_attribute(attr).changed?(old, value) end end end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index c3e601a208..5203b30462 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -72,18 +72,20 @@ module ActiveRecord @attributes.delete(attr_name) column = column_for_attribute(attr_name) + unless has_attribute?(attr_name) || self.class.columns_hash.key?(attr_name) + raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'" + end + # If we're dealing with a binary column, write the data to the cache # so we don't attempt to typecast multiple times. - if column && column.binary? + if column.binary? @attributes[attr_name] = value end - if column && should_type_cast + if should_type_cast @raw_attributes[attr_name] = column.type_cast_for_write(value) - elsif !should_type_cast || @raw_attributes.has_key?(attr_name) - @raw_attributes[attr_name] = value else - raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{attr_name}'" + @raw_attributes[attr_name] = value end end end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index e6603f28be..b3c02d29cb 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -80,6 +80,25 @@ class ReflectionTest < ActiveRecord::TestCase assert_equal :integer, @first.column_for_attribute("id").type end + def test_non_existent_columns_return_null_object + column = @first.column_for_attribute("attribute_that_doesnt_exist") + assert_equal "attribute_that_doesnt_exist", column.name + assert_equal nil, column.sql_type + assert_equal nil, column.type + assert_not column.number? + assert_not column.text? + assert_not column.binary? + end + + def test_non_existent_columns_are_identity_types + column = @first.column_for_attribute("attribute_that_doesnt_exist") + object = Object.new + + assert_equal object, column.type_cast(object) + assert_equal object, column.type_cast_for_write(object) + assert_equal object, column.type_cast_for_database(object) + end + def test_reflection_klass_for_nested_class_name reflection = MacroReflection.new(:company, nil, nil, { :class_name => 'MyApplication::Business::Company' }, ActiveRecord::Base) assert_nothing_raised do |