Skip to content

Instantly share code, notes, and snippets.

@dhh
Created May 19, 2011 19:27
Show Gist options
  • Save dhh/981520 to your computer and use it in GitHub Desktop.
Save dhh/981520 to your computer and use it in GitHub Desktop.
bulk api
# Bulk API design
#
# resources :posts
class PostsController < ActiveController::Base
# GET /posts/1,4,50,90
# post_url([ @post, @post ])
def show_many
@posts = Post.find(params[:ids])
end
# PUT /posts/1,4,50,90
def update_many
@posts = Post.find(params[:ids])
Post.transaction do
@posts.each do |post|
post.update_attributes!(params[:posts][post.id])
end
end
end
# POST /posts/many
def create_many
end
# DELETE /posts/1,4,50,90
def destroy_many
end
end
@grimen
Copy link

grimen commented May 25, 2011

@sinsiliux, the first case could be avoided by having params[:ids] to be equivalent to params[:id].split(','). That's how I handled it at least, but maybe I was playing with fire. :)

@andriusch
Copy link

@grimen what I wanted was to return all records when params[:ids] is empty and selected records when it's present.

@grimen
Copy link

grimen commented May 25, 2011

@sinsiliux I just noticed where(:id => params[:ids]) != where(:id => nil) - I think this was not the case in Rails 2.3.x (old finders). Anyway, my basic point was that for me params[:ids] should be same as params[:id] to avoid singular vs. plural getting in the way.

@jmorton
Copy link

jmorton commented May 27, 2011

@grimen I too wonder if handling the one-or-many cases using a single action makes sense. I'm experimenting with this before_filter:

def separate_bulk_ids
  if params[:id].present?
    params[:ids] = params[:id].split(',')
    params[:id] = params[:ids].first
  end
end

Is it surprising that params[:id] is always the first of many IDs? Aside from the obvious case of overwriting an explicitly passed :ids parameter, when would this cause problems? Anyhow, here's how I make use of it in a trivial #update example.

def update
  # Gracefully ignores invalid IDs
  @posts = Post.where(:id => params[:ids])  
  @posts.each do |post|
    # Enforce policy if desired on each post...
    post.update_attributes(params[:posts][post.id.to_s]) 
  end
  # What results are returned considering some updates may have failed?
end

I've created a little Rails app with some different examples and tests.

https://github.com/jmorton/bulk-example/blob/tolerant/app/controllers/posts_controller.rb
https://github.com/jmorton/bulk-eaxample/blob/strict/app/controllers/posts_controller.rb

@jamesarosen
Copy link

If I recall correctly, Richardson's Restful Web Services recommends , for dimensional things (like /locations/lat,long/) and ; for lists of things (like /posts/1;2;3). Allamaraju's Restful Web Services Cookbook, on the other hand, doesn't express a preference between the two.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment