aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/dirty.rb4
-rw-r--r--activerecord/test/cases/dirty_test.rb27
2 files changed, 30 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/dirty.rb b/activerecord/lib/active_record/dirty.rb
index b32e17e990..a7d767486c 100644
--- a/activerecord/lib/active_record/dirty.rb
+++ b/activerecord/lib/active_record/dirty.rb
@@ -142,9 +142,11 @@ module ActiveRecord
def field_changed?(attr, old, value)
if column = column_for_attribute(attr)
- if column.type == :integer && column.null && old.nil?
+ if column.type == :integer && column.null && (old.nil? || old == 0)
# For nullable integer 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)
value = nil if value.blank?
else
value = column.type_cast(value)
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index d70a787208..e5e022050d 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -55,6 +55,33 @@ class DirtyTest < ActiveRecord::TestCase
end
end
+ def test_zero_to_blank_marked_as_changed
+ pirate = Pirate.new
+ pirate.catchphrase = "Yarrrr, me hearties"
+ pirate.parrot_id = 1
+ pirate.save
+
+ # check the change from 1 to ''
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+ pirate.parrot_id = ''
+ assert pirate.parrot_id_changed?
+ assert_equal([1, nil], pirate.parrot_id_change)
+ pirate.save
+
+ # check the change from nil to 0
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+ pirate.parrot_id = 0
+ assert pirate.parrot_id_changed?
+ assert_equal([nil, 0], pirate.parrot_id_change)
+ pirate.save
+
+ # check the change from 0 to ''
+ pirate = Pirate.find_by_catchphrase("Yarrrr, me hearties")
+ pirate.parrot_id = ''
+ assert pirate.parrot_id_changed?
+ assert_equal([0, nil], pirate.parrot_id_change)
+ end
+
def test_object_should_be_changed_if_any_attribute_is_changed
pirate = Pirate.new
assert !pirate.changed?