Search code examples
ruby-on-railsruby-on-rails-3activerecordassociationsupdate-attributes

How to accomplish an update_attributes without actually saving the changes


Possible Duplicate:
Rails update_attributes without save?

Fundamentally, I want to do an ActiveRecord "update_attributes" while leaving the ActiveRecord changes pending. Is there a way to accomplish this? Read on if you are wondering why I would want this.

I have a form consisting of three parts: a static portion (text fields independent of each other), a set of selections (grows as entries are filled in), and a section showing the effects of the selections upon a group of dependent objects. Changing the selections requires a round trip to the server to determine the effects and some of the selections affect the choices for future selections. The selections are modeled as a has_many association from the basic model. E.g. (note that the [] entries designate HTML-SELECTs)

Include [section]
  Exclude [subsection]
  Exclude [subsection]
Include [section]
  Exclude [subsection]
...

I have set the form up as a typical nested-attributes form. When a selection is changed, I post back the fields with AJAX such that I'm getting the typical params hash (e.g. params[:basemodel][associated_models_attributes][0][:field_name]). I'd like to get this into an unsaved ActiveRecord so that the partials I'm already using to generate parts of the original page can be used to generate the JS response (I'm using a js.erb file for this). Using Basemodel.new(params[:basemodel]) gives the error

"ActiveRecord::RecordNotFound (Couldn't find AssociatedModel with ID=1 for Basemodel with ID=)

This is happening (I think) because the IDs from the existing associated records (which have non-blank IDs in the current record) do not match up with the blank IDs that would be generated from the "new" call.

I could do something really kludgy and create something that looks like an ActiveRecord (at least enough like it to satisfy my partials) but I have to think that this is a problem that is common enough that there's a good solution for it.


Solution

  • Depending on the source of ActiveRecord::Persistence#update_attributes

    # File activerecord/lib/active_record/persistence.rb, line 127
    def update_attributes(attributes)
      # The following transaction covers any possible database side-effects of the
      # attributes assignment. For example, setting the IDs of a child collection.
      with_transaction_returning_status do
        self.attributes = attributes
        save
      end
    end
    

    you can assign attributes to your model by using

    model.attributes = attributes
    

    where attributes is a hash of model fields etc.