public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Dirty attributes aren't cleared if save fails. [#174 state:resolved]

Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
fxn (author)
Mon May 12 15:46:57 -0700 2008
jeremy (committer)
Mon May 12 17:04:17 -0700 2008
commit  593e21d6aedcc05d744be4996bd7180edce57efe
tree    27cb4e5dbaab49554d2a5bde9971a5c9c6521c88
parent  a425cd147363a0e8d7e17177ef252dd760197f15
...
69
70
71
72
73
 
74
75
76
77
 
 
 
 
78
79
80
 
81
82
83
 
84
 
85
86
87
...
69
70
71
 
 
72
73
 
 
 
74
75
76
77
78
79
 
80
81
 
 
82
83
84
85
86
87
0
@@ -69,19 +69,19 @@ module ActiveRecord
0
       changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h }
0
     end
0
 
0
-
0
-    # Clear changed attributes after they are saved.
0
+    # Attempts to +save+ the record and clears changed attributes if successful.
0
     def save_with_dirty(*args) #:nodoc:
0
-      save_without_dirty(*args)
0
-    ensure
0
-      changed_attributes.clear
0
+      if status = save_without_dirty(*args)
0
+        changed_attributes.clear
0
+      end
0
+      status
0
     end
0
 
0
-    # Clear changed attributes after they are saved.
0
+    # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
0
     def save_with_dirty!(*args) #:nodoc:
0
-      save_without_dirty!(*args)
0
-    ensure
0
+      status = save_without_dirty!(*args)
0
       changed_attributes.clear
0
+      status
0
     end
0
 
0
     private
...
78
79
80
81
 
82
83
84
...
115
116
117
 
 
 
 
 
 
 
 
 
 
 
 
118
119
120
...
123
124
125
 
 
 
 
 
 
 
126
...
78
79
80
 
81
82
83
84
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
135
136
137
138
139
140
141
142
143
144
145
0
@@ -78,7 +78,7 @@ class DirtyTest < ActiveRecord::TestCase
0
   end
0
 
0
   def test_association_assignment_changes_foreign_key
0
-    pirate = Pirate.create!
0
+    pirate = Pirate.create!(:catchphrase => 'jarl')
0
     pirate.parrot = Parrot.create!
0
     assert pirate.changed?
0
     assert_equal %w(parrot_id), pirate.changed
0
@@ -115,6 +115,18 @@ class DirtyTest < ActiveRecord::TestCase
0
     end
0
   end
0
 
0
+  def test_changed_attributes_should_be_preserved_if_save_failure
0
+    pirate = Pirate.new
0
+    pirate.parrot_id = 1
0
+    assert !pirate.save
0
+    check_pirate_after_save_failure(pirate)
0
+
0
+    pirate = Pirate.new
0
+    pirate.parrot_id = 1
0
+    assert_raises(ActiveRecord::RecordInvalid) { pirate.save! }
0
+    check_pirate_after_save_failure(pirate)
0
+  end
0
+
0
   private
0
     def with_partial_updates(klass, on = true)
0
       old = klass.partial_updates?
0
@@ -123,4 +135,11 @@ class DirtyTest < ActiveRecord::TestCase
0
     ensure
0
       klass.partial_updates = old
0
     end
0
+
0
+    def check_pirate_after_save_failure(pirate)
0
+      assert pirate.changed?
0
+      assert pirate.parrot_id_changed?
0
+      assert_equal %w(parrot_id), pirate.changed
0
+      assert_nil pirate.parrot_id_was
0
+    end
0
 end
...
4
5
6
 
 
7
...
4
5
6
7
8
9
0
@@ -4,4 +4,6 @@ class Pirate < ActiveRecord::Base
0
   has_many :treasures, :as => :looter
0
 
0
   has_many :treasure_estimates, :through => :treasures, :source => :price_estimates
0
+
0
+  validates_presence_of :catchphrase
0
 end

Comments