public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Ensure nil to '' doesn't get recorded by dirty for nullable integer 
columns. [#150 state:resolved] [Jason Dew, Pratik]
lifo (author)
Tue May 20 12:50:46 -0700 2008
commit  281edce6db8accc7d4a0e9ab01892631d9d0ebc3
tree    6d56e7bae4636d1cab9da18c8880880206c2bfa1
parent  73c59638549686fccc749ffd3ac53cb533c5fd61
...
117
118
119
120
121
122
123
124
125
126
127
 
128
129
130
...
138
139
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
142
...
117
118
119
 
 
 
 
 
 
 
 
120
121
122
123
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
0
@@ -117,14 +117,7 @@ module ActiveRecord
0
         # The attribute already has an unsaved change.
0
         unless changed_attributes.include?(attr)
0
           old = clone_attribute_value(:read_attribute, attr)
0
-
0
- # Remember the original value if it's different.
0
- typecasted = if column = column_for_attribute(attr)
0
- column.type_cast(value)
0
- else
0
- value
0
- end
0
- changed_attributes[attr] = old unless old == typecasted
0
+ changed_attributes[attr] = old if field_changed?(attr, old, value)
0
         end
0
 
0
         # Carry on.
0
@@ -138,5 +131,20 @@ module ActiveRecord
0
           update_without_dirty
0
         end
0
       end
0
+
0
+ def field_changed?(attr, old, value)
0
+ if column = column_for_attribute(attr)
0
+ if column.type == :integer && column.null && old.nil?
0
+ # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values.
0
+ # Hence we don't record it as a change if the value changes from nil to ''.
0
+ value = nil if value.blank?
0
+ else
0
+ value = column.type_cast(value)
0
+ end
0
+ end
0
+
0
+ old != value
0
+ end
0
+
0
   end
0
 end
...
44
45
46
 
 
 
 
 
 
 
 
 
 
47
48
49
...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
0
@@ -44,6 +44,16 @@ class DirtyTest < ActiveRecord::TestCase
0
     assert_nil pirate.catchphrase_change
0
   end
0
 
0
+ def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank
0
+ pirate = Pirate.new
0
+
0
+ ["", nil].each do |value|
0
+ pirate.parrot_id = value
0
+ assert !pirate.parrot_id_changed?
0
+ assert_nil pirate.parrot_id_change
0
+ end
0
+ end
0
+
0
   def test_object_should_be_changed_if_any_attribute_is_changed
0
     pirate = Pirate.new
0
     assert !pirate.changed?

Comments

    No one has commented yet.