Skip to content

Commit

Permalink
Dirty attributes aren't cleared if save fails. [#174 state:resolved]
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy Kemper <jeremy@bitsweat.net>
  • Loading branch information
fxn authored and jeremy committed May 13, 2008
1 parent a425cd1 commit 593e21d
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
16 changes: 8 additions & 8 deletions activerecord/lib/active_record/dirty.rb
Expand Up @@ -69,19 +69,19 @@ def changes
changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h } changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h }
end end



# Attempts to +save+ the record and clears changed attributes if successful.
# Clear changed attributes after they are saved.
def save_with_dirty(*args) #:nodoc: def save_with_dirty(*args) #:nodoc:
save_without_dirty(*args) if status = save_without_dirty(*args)
ensure changed_attributes.clear
changed_attributes.clear end
status
end end


# Clear changed attributes after they are saved. # Attempts to <tt>save!</tt> the record and clears changed attributes if successful.
def save_with_dirty!(*args) #:nodoc: def save_with_dirty!(*args) #:nodoc:
save_without_dirty!(*args) status = save_without_dirty!(*args)
ensure
changed_attributes.clear changed_attributes.clear
status
end end


private private
Expand Down
21 changes: 20 additions & 1 deletion activerecord/test/cases/dirty_test.rb
Expand Up @@ -78,7 +78,7 @@ def test_attribute_will_change!
end end


def test_association_assignment_changes_foreign_key def test_association_assignment_changes_foreign_key
pirate = Pirate.create! pirate = Pirate.create!(:catchphrase => 'jarl')
pirate.parrot = Parrot.create! pirate.parrot = Parrot.create!
assert pirate.changed? assert pirate.changed?
assert_equal %w(parrot_id), pirate.changed assert_equal %w(parrot_id), pirate.changed
Expand Down Expand Up @@ -115,6 +115,18 @@ def test_partial_update
end end
end end


def test_changed_attributes_should_be_preserved_if_save_failure
pirate = Pirate.new
pirate.parrot_id = 1
assert !pirate.save
check_pirate_after_save_failure(pirate)

pirate = Pirate.new
pirate.parrot_id = 1
assert_raises(ActiveRecord::RecordInvalid) { pirate.save! }
check_pirate_after_save_failure(pirate)
end

private private
def with_partial_updates(klass, on = true) def with_partial_updates(klass, on = true)
old = klass.partial_updates? old = klass.partial_updates?
Expand All @@ -123,4 +135,11 @@ def with_partial_updates(klass, on = true)
ensure ensure
klass.partial_updates = old klass.partial_updates = old
end end

def check_pirate_after_save_failure(pirate)
assert pirate.changed?
assert pirate.parrot_id_changed?
assert_equal %w(parrot_id), pirate.changed
assert_nil pirate.parrot_id_was
end
end end
2 changes: 2 additions & 0 deletions activerecord/test/models/pirate.rb
Expand Up @@ -4,4 +4,6 @@ class Pirate < ActiveRecord::Base
has_many :treasures, :as => :looter has_many :treasures, :as => :looter


has_many :treasure_estimates, :through => :treasures, :source => :price_estimates has_many :treasure_estimates, :through => :treasures, :source => :price_estimates

validates_presence_of :catchphrase
end end

0 comments on commit 593e21d

Please sign in to comment.