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

What does minus mean in “exec 3>&-” and how do I use it?

bash redirect terminal stdout sh

I often have trouble figuring out certain language constructs because they won't register when googling or duckduckgoing them. With a bit of experimenting, it's often simple to figure it out, but I...

how find a number of specific sub-string in a string

java regex

hi i'm starting to learn java but i have a problem with regex i have a string like this

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.