Best Practice for Bulk Update in Controller Best Practice for Bulk Update in Controller ruby ruby

Best Practice for Bulk Update in Controller


I see that you tagged your question with REST.

To do it RESTfully, you need to think about the collection or the update itself as the resource.

Say you are working with Product objects.

You might PUT to /product_batches/[some identifier], which would call ProductBatchesController#update, but then you are stuck wondering what goes in [some identifier]. You could make ProductBatch a singular resource and then you wouldn't need an id.

Better might be to POST to /product_bulk_updates, which would call ProductBulkUpdatesController#create

class ProductBulkUpdatesController < ApplicationController  def create    # your magic here    # - update_all if you are making the same change to all Products    # - looping through the hashes in params[products] if you are passing in distinct changes to each.  endend

Here's another thread:Bulk Collection Manipulation through a REST (RESTful) API


I don't think there is a standard way. You may use update_attributes (example with PostsController):

def update_bulk  @posts = Post.where(:id => params[:ids])  # wrap in a transaction to avoid partial updates (and move to the model)  if @posts.all? { |post| post.update_attributes(params[:post]) }    redirect_to(posts_url)  else    redirect_to(:back)  endend

Or use update_all, but notice that neither callbacks nor validations will be called:

def update_bulk  Post.where(:id => params[:ids]).update_all(params[:post])  redirect_to(posts_url)end


If you're fortunate enough to be working in Rails 3 then you should make sure to check out ActiveRecord::Relation#update_all or ActiveRecord::Base#update_all in Rails 2:

It's much bettter to construct a single SQL update statement than do a full SQL round trip to update the elements.

Important Note: This is truely a bulk update using a SQL update statement. It will not instantiate any ActiveRecord objects since the update is performed purely in SQL. As such ActiveRecord callbacks and validations will not be called.

Examples from the URL above:

# Update all customers with the given attributesCustomer.update_all :wants_email => true# Conditions from the current relation also worksBook.where('title LIKE ?', '%Rails%').update_all(:author => 'David')

Note: As far as I can tell from posts on the internet, this functionality was somewhere between buggy and broken in Rails 3.0.3, 3.0.7 - 3.0.9.

I didn't discover the feature until 3.1.0, so I can't corroborate.