This project is archived and is in readonly mode.

#922 ✓resolved
2 College Bums

has_many through transaction rollback

Reported by 2 College Bums | August 28th, 2008 @ 04:33 AM | in 3.x

When saving a model that contains a has_many through association, the entire transaction fails to rollback when the validation fails. Specifically xxx_ids= should not modify the association unless all validations pass.

Example: Let's assume we have a Paper model that contains a title attribute and a has_many through relationship with Categories. We validate to ensure a paper has at least one category and the title is not invalid.

If the title is invalid and the categories are empty and an "update_attributes" occurs even after the validation fails, all associations to categories are lost. The title is not updated as expected. Preferably, the association to categories would not be affected unless a save is successful.

a = Paper.first
a.categories # => [#category1, #category2]
a.update_attributes(:category_ids => [], :title => "invalid") # => false
a.categories # => []
a.title # => "invalid"
a.valid? # => false
a.errors.full_messages # => ["title cannot be invalid", "At least one category must be assigned"]
a.title # => "Original"
a.categories # => []
a.valid? # => false

There is a quick fix that doesn't completely solve the problem. In the model where the update_attributes occurs we can force a "rollback" using the following code:

  def update_attributes_with_rollback(*args)
    old_category_ids = self.category_ids
    saved_properly = update_attributes_without_rollback(*args)
    self.category_ids = old_category_ids unless saved_properly
  alias_method_chain :update_attributes, :rollback

Here are some resources which aided us and may help:

Comments and changes to this ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>

Referenced by