diff options
-rw-r--r-- | activerecord/lib/active_record/attribute_methods/dirty.rb | 20 | ||||
-rw-r--r-- | activerecord/test/cases/nested_attributes_test.rb | 10 |
2 files changed, 25 insertions, 5 deletions
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index f61e016f46..586a189011 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -79,11 +79,8 @@ module ActiveRecord def field_changed?(attr, old, value) if column = column_for_attribute(attr) - if column.number? && column.null && (old.nil? || old == 0) && value.blank? - # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values. - # Hence we don't record it as a change if the value changes from nil to ''. - # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll - # be typecast back to 0 (''.to_i => 0) + if column.number? && (changes_from_nil_to_empty_string?(column, old, value) || + changes_from_zero_to_string?(old, value)) value = nil else value = column.type_cast(value) @@ -96,6 +93,19 @@ module ActiveRecord def clone_with_time_zone_conversion_attribute?(attr, old) old.class.name == "Time" && time_zone_aware_attributes && !self.skip_time_zone_conversion_for_attributes.include?(attr.to_sym) end + + def changes_from_nil_to_empty_string?(column, old, value) + # For nullable numeric columns, NULL gets stored in database for blank (i.e. '') values. + # Hence we don't record it as a change if the value changes from nil to ''. + # If an old value of 0 is set to '' we want this to get changed to nil as otherwise it'll + # be typecast back to 0 (''.to_i => 0) + column.null && (old.nil? || old == 0) && value.blank? + end + + def changes_from_zero_to_string?(old, value) + # For columns with old 0 and value non-empty string + old == 0 && value.present? && value != '0' + end end end end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 817898f190..16b1eb040e 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -772,6 +772,16 @@ module NestedAttributesOnACollectionAssociationTests assert_nothing_raised(NoMethodError) { @pirate.save! } end + def test_numeric_colum_changes_from_zero_to_no_empty_string + Man.accepts_nested_attributes_for(:interests) + Interest.validates_numericality_of(:zine_id) + man = Man.create(:name => 'John') + interest = man.interests.create(:topic=>'bar',:zine_id => 0) + assert interest.save + + assert !man.update_attributes({:interests_attributes => { :id => interest.id, :zine_id => 'foo' }}) + end + private def association_setter |