diff options
5 files changed, 47 insertions, 2 deletions
diff --git a/actionview/lib/action_view/helpers/tags/base.rb b/actionview/lib/action_view/helpers/tags/base.rb index f8abb19698..7740c60eac 100644 --- a/actionview/lib/action_view/helpers/tags/base.rb +++ b/actionview/lib/action_view/helpers/tags/base.rb @@ -32,12 +32,19 @@ module ActionView unless object.nil? method_before_type_cast = @method_name + "_before_type_cast" - object.respond_to?(method_before_type_cast) ? - object.send(method_before_type_cast) : + if value_came_from_user?(object) && object.respond_to?(method_before_type_cast) + object.public_send(method_before_type_cast) + else value(object) + end end end + def value_came_from_user?(object) + method_name = "#{@method_name}_came_from_user?" + !object.respond_to?(method_name) || object.public_send(method_name) + end + def retrieve_object(object) if object object diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb index fa8d11d08b..e4fd797924 100644 --- a/actionview/test/template/form_helper_test.rb +++ b/actionview/test/template/form_helper_test.rb @@ -101,6 +101,7 @@ class FormHelperTest < ActionView::TestCase def @post.to_key; [123]; end def @post.id; 0; end def @post.id_before_type_cast; "omg"; end + def @post.id_came_from_user?; true; end def @post.to_param; '123'; end @post.persisted = true @@ -908,6 +909,22 @@ class FormHelperTest < ActionView::TestCase ) end + def test_inputs_dont_use_before_type_cast_when_value_did_not_come_from_user + def @post.id_came_from_user?; false; end + assert_dom_equal( + %{<textarea id="post_id" name="post[id]">\n0</textarea>}, + text_area("post", "id") + ) + end + + def test_inputs_use_before_typecast_when_object_doesnt_respond_to_came_from_user + class << @post; undef id_came_from_user?; end + assert_dom_equal( + %{<textarea id="post_id" name="post[id]">\nomg</textarea>}, + text_area("post", "id") + ) + end + def test_text_area_with_html_entities @post.body = "The HTML Entity for & is &" assert_dom_equal( diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb index 88536eaac0..51e4fae62e 100644 --- a/activerecord/lib/active_record/attribute.rb +++ b/activerecord/lib/active_record/attribute.rb @@ -74,6 +74,10 @@ module ActiveRecord true end + def came_from_user? + false + end + def ==(other) self.class == other.class && name == other.name && @@ -99,6 +103,10 @@ module ActiveRecord def type_cast(value) type.type_cast_from_user(value) end + + def came_from_user? + true + end end class WithCastValue < Attribute # :nodoc: diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index fd61febd57..56c1898551 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -28,6 +28,7 @@ module ActiveRecord included do attribute_method_suffix "_before_type_cast" + attribute_method_suffix "_came_from_user?" end # Returns the value of the attribute identified by +attr_name+ before @@ -66,6 +67,10 @@ module ActiveRecord def attribute_before_type_cast(attribute_name) read_attribute_before_type_cast(attribute_name) end + + def attribute_came_from_user?(attribute_name) + @attributes[attribute_name].came_from_user? + end end end end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 01ee1234a2..359503db98 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -888,6 +888,14 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_not_equal ['id'], @target.column_names end + def test_came_from_user + model = @target.first + + assert_not model.id_came_from_user? + model.id = "omg" + assert model.id_came_from_user? + end + private def new_topic_like_ar_class(&block) |