Build array of objects from params hash after Transaction block fails, Rails

I have a form where a user can update multiple resources at the same time. The transaction block makes the form atomic: if one validation fails for any of the resources being updated, then none of the resources get updated, and active record rollsback all changes.

When transaction fails, I want to render the form again, display the same input that the user entered along with errors next to each of the error input fields which prevented the transaction from going through.

The transaction block works. What I am having trouble with is building the array of objects from the params log. Each index of the array should contain a hash which holds key/value pairs of all the attributes of a specific resource.

UDPATE: BELOW IS THE ANSWER CODE THANKS TO THE RESPONSES

Code:

def update_multiple
  begin
    User.transaction do
      params[:users].each do |k, v|
      User.find(k).update!(v)
    end
    flash[:notice] = "Update Successful"
    redirect_to :users and return
  end
  rescue
    @users = []
    params[:users].each do |k,v|
      @users.push(User.new({:id => k}.merge(v))) 
    end
    flash[:error] = "Errors found"
    render :edit_multiple and return
  end
end

And for good measure, here is what the passed in parameters looks like in the log. This transaction fails because the name attribute must be at least 3 characters long.

Parameters: {"utf8"=>"✓", "authenticity_token"=>"xyz=", "users"=>{"15"=>
{"name"=>"Neil", "age"=>"11"}, "16"=>{"name"=>"z", "age"=>"33"}, "17"=>
{"name"=>"John", "age"=>"99"}}, "commit"=>"Submit Changes"}

Thanks in advance! Any way to write this code better in ruby is much appreciated as well.

Answers


Ok, so you're trying to iterate through a list of objects in your params using a for_each and an external iterator, you really don't want to do that. I'd suggest something like this:

params[:users].each do |k,v|
  # k is the "key" of each user while v is the values associated with each key
  @users.push(User.new(:id => k, v)
  # I'm doing this in my head so you might need:
  # @users.push(User.new({:id => k}.merge(v)) 
  # if you start getting errors about looking for a proper hash or something
  # I can't remember how good Rails/Ruby is at recognizing nested hashes
end

That should produce a new user for each user object passed in using the ID provided and the values associated with each value.


Need Your Help

Handle requests to several classes within the same PHP SOAP server

php web-services soap wsdl

Is that possible to have a single PHP SOAP server which will handle requests to several classes (services)?