From 634ecdbf1b6401ded0e145b1e7c7f4808ad89398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Sat, 3 Jan 2015 23:42:59 -0300 Subject: Return a null column from `column_for_attribute` when no column exists. This reverts commit ae96f229f6501d8635811d6b22d75d43cdb880a4. Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/attribute_methods.rb --- activerecord/CHANGELOG.md | 4 ++++ .../associations/preloader/association.rb | 4 ++-- .../lib/active_record/attribute_methods.rb | 16 ++++++---------- .../active_record/connection_adapters/column.rb | 6 ++++++ activerecord/test/cases/reflection_test.rb | 22 ++++++++++++++++++---- 5 files changed, 36 insertions(+), 16 deletions(-) (limited to 'activerecord') diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 17e2c22a38..34b7502d3d 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. + + *Rafael Mendonça França* + * Remove deprecated `serialized_attributes`. *Rafael Mendonça França* diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index a6e1a24360..afcaa5d55a 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -104,11 +104,11 @@ module ActiveRecord end def association_key_type - @klass.type_for_attribute(association_key_name.to_s).type + @klass.column_for_attribute(association_key_name).type end def owner_key_type - @model.type_for_attribute(owner_key_name.to_s).type + @model.column_for_attribute(owner_key_name).type end def load_slices(slices) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index b7edac791e..8f165fb1dc 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -192,7 +192,8 @@ module ActiveRecord end # Returns the column object for the named attribute. - # Returns nil if the named attribute does not exist. + # Returns a +ActiveRecord::ConnectionAdapters::NullColumn+ if the + # named attribute does not exist. # # class Person < ActiveRecord::Base # end @@ -202,17 +203,12 @@ module ActiveRecord # # => # # # person.column_for_attribute(:nothing) - # # => nil + # # => #, ...> def column_for_attribute(name) - column = columns_hash[name.to_s] - if column.nil? - ActiveSupport::Deprecation.warn(<<-MSG.squish) - `#column_for_attribute` will return a null object for non-existent - columns in Rails 5. Use `#has_attribute?` if you need to check for - an attribute's existence. - MSG + name = name.to_s + columns_hash.fetch(name) do + ConnectionAdapters::NullColumn.new(name) end - column end end diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 65d8b1a8ab..d7f999c3c6 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -77,6 +77,12 @@ module ActiveRecord [self.class, name, default, cast_type, sql_type, null, default_function] end end + + class NullColumn < Column + def initialize(name) + super name, nil, Type::Value.new + end + end end # :startdoc: end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index e86b892a0a..a2252a836f 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -80,10 +80,24 @@ class ReflectionTest < ActiveRecord::TestCase assert_equal :integer, @first.column_for_attribute("id").type end - def test_non_existent_columns_return_nil - assert_deprecated do - assert_nil @first.column_for_attribute("attribute_that_doesnt_exist") - end + def test_non_existent_columns_return_null_object + column = @first.column_for_attribute("attribute_that_doesnt_exist") + assert_instance_of ActiveRecord::ConnectionAdapters::NullColumn, column + 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_from_database(object) + assert_equal object, column.type_cast_from_user(object) + assert_equal object, column.type_cast_for_database(object) end def test_reflection_klass_for_nested_class_name -- cgit v1.2.3