Bulk update objects using a shape in rails
I have a human model and a quotes model. Each person can have many quotes associated with them, which in turn is associated with things like Author, Text, Url. In practice, only one person actually has a quote object, but all people can potentially have it.
I try to keep the quotes dirty, simple volumetric instrument. As is the case, users can enter quotes, and the admin can go and have all the quotes of a particular person (but, in practice, only one of them will have them) and check the box that sets the boolean asserted to 0 or 1 When quotes are actually displayed, they are filtered by this field.
I am very confused while trying to create a form that updates the whole thing in bulk. I got a form to display them all like this:
<% form_for :quotes, :html => { :method => :put }, :url => {:controller => "quote", :action => "bulk_update", } do |quote_form| %>
<% @person.quotes.each do |quote| %>
<p>
<% fields_for "quotes[id][]", quote do |fields| %>
Text....
<%= fields.check_box :approved %><br><br>
<% end %>
</p>
<% end %>
<%= submit_tag 'Update' %>
<% end %>
I just have an incredibly generic character in my bulk update controller, which is basically like a regular update controller. I'm not sure what to put in there. I could try to put in all the quotes I probably need, but I don't know how to get to this variable, since I am doing all of this from the Person view, etc. The controller looks something like this:
def bulk_update
@quote = Quote.find(params[:id])
end
I am guessing that I am confused with the ID that should be there and what should be passed. Should the person ID be part of this? As I said, I don't care if technically all the quotes will appear on this page, they don't need to be sorted by user.
I get parameters that look like this:
"quotes" => {"id" => {"6" => {"approved" => "0"}, ..
but it complains about not finding a quote without an id. I don't care about the ID as I want them all to be updated. It seems that this particular structure will display multiple ids, but maybe (maybe) I should change my controller to compensate for this, but don't know how. It also doesn't work when I try to remove quotes from the hash par tof and just have "id" => {"6" => {"approved" => "0"}, .. as my parameters.
EDIT: I found an instruction called update_all, but I don't know how to selectively pass it what I need ...
source to share
I found the following approach should be flexible, especially for error handling:
def bulk_update
quotes = params["quotes"]["id"]
quotes.each do |quote_id,quote_attrs|
quote = Quote.find(quote_id)
quote.update_attributes(quote_attrs)
# Other logic of interest like error handling
# . . .
end
# Don't forget to render or redirect to the proper view
end
Update
The correct way to do this is to move the update logic into the model:
class QuotesController < ApplicationController
def bulk_update
errors = Quote.bulk_update(params["quotes"]["id"])
# Other logic of interest like error handling
# . . .
# Don't forget to render or redirect to the proper view
end
end
class Quote < ActiveRecord::Base
def bulk_update
errors = {}
quotes.each do |quote_id,quote_attrs|
quote = Quote.find(quote_id)
unless quote.update_attributes(quote_attrs)
errors[quote_id] = qoute.errors
end
end
errors
end
end
source to share
I would do something like this:
def self.bulk_update(attributes)
where(id: attributes.keys).each_with_object({}) do |quote, errors|
unless quote.update_attributes(attributes["#{quote.id}"])}
errors["#{quote.id}"] = entry.errors
end
end
In this method, you are only loading quotes.
Gregory Chorion -
source to share
Looking at this code:
def bulk_update
quotes = params["quotes"]["id"]
quotes.each do |quote_id,quote_attrs|
quote = Quote.find(quote_id)
quote.update_attributes(quote_attrs)
end
end
I thought it would be more concise to do this:
Quote.where(:condition => "value").collect{|x| x.update_attributes(quote_attrs)}
source to share