Simply_RESTful and Bulk Import URLs

Hi,

I have a people controller, and want to import bulk import multiple
people from a CSV file.

In my routes.rb file I have:

map.resource :person

Now, it’s a little unclear to me how to further configure the routes to
allow me to add the following URLs:

I need a URL to choose a file to upload, so I need an HTML ‘frontend’
for it, so I figured the following URL fits into the REST/CRUD paradigm:

/people;bulk_import (using a GET method)

Once I have picked my CSV file, I need to do a POST to perform the
actual bulk import.

Here I was thinking of either:

/people/;bulk_import (using a POST method)

or

/people/bulk_import (using a POST method).

I’m getting a bit confused on how to think about this ‘new’ REST/CRUD
paradigm, especially in terms of URLs, and then using the simply_restful
plugin to manage the named routes.

Can somebody clear this up for me before my head explodes.

Thanks
Joerg

Joerg D. wrote:

Hi,

I have a people controller, and want to import bulk import multiple
people from a CSV file.

In my routes.rb file I have:

map.resource :person

Now, it’s a little unclear to me how to further configure the routes to
allow me to add the following URLs:

I need a URL to choose a file to upload, so I need an HTML ‘frontend’
for it, so I figured the following URL fits into the REST/CRUD paradigm:

/people;bulk_import (using a GET method)

Once I have picked my CSV file, I need to do a POST to perform the
actual bulk import.

I’m still trying to figure out this RESTful stuff as well, but my
understanding is that these complications about the verb ususally mean
you need a new noun. So rather than “people;bulk_import” how about

GET bulk_people;new
POST bulk_people

Or perhaps even better is to roll it into your people create action.
This way it’s still restful, but also supports other ways of creating
records at the same url based on passed parameters.

#people controller
def create
if params[:csv]
create_people_from_csv(params[:csv])
else
Person.create(params[:person])
end
end

private
def create_people_from_csv(csv)
…parse csv…
csv.each {|line| Person.create(line)}
end

Cool - that’s awesome Jeremy thanks. As simple as that hey.

So to summarize the REST/CRUD way:

  1. if you need any extra actions other than the 4 crud verbs, then
    either you need to introduce a new noun into your model, or - in this
    case - where it still makes sense to add these extra actions onto the
    existing people noun, then add them with a ; to the end of the url (eg
    /people;upload). Using the simply_restful plugin allows you to easily
    create these kind of urls.

  2. each action in your controller should respond to only one http
    method.

  3. Be reasonable. You don’t have to take things to the extreme.

Joerg

Jeremy K. wrote:

On Jul 31, 2006, at 10:20 AM, Joerg D. wrote:

Now, it’s a little unclear to me how to further configure the
routes to
allow me to add the following URLs:

I need a URL to choose a file to upload, so I need an HTML ‘frontend’
for it, so I figured the following URL fits into the REST/CRUD
paradigm:

/people;bulk_import (using a GET method)

GET /people;upload

map.resource :person, :collection => { :upload => :get, :import
=> :post }

class PeopleController < ApplicationController
# Html form to upload CSV file.
def upload
end

 # Handle CSV file upload.
 def import
   Person.create(csv_to_array_of_person_hashes(params[:csv].read)
 end

end

To take it a bit further, register the CSV MIME type

register Mime::CSV as ‘text/csv’ with synonym ‘text/c-s-v’

Mime::Type.register :csv, ‘text/csv’, [‘text/comma-separated-values’]

so you can respond_to csv in index, show, etc

respond_to do |wants|
wants.html # render the rhtml template
wants.csv { render :text => person.to_csv }
end

and automatically parse CSV request bodies into @params

ActionController::Base.param_parsers[Mime::CSV] = Proc.new do |data|
# return a params hash from the csv data (better have a header
row…)
csv_to_person_hash(data)
end

so you can create and update with CSV as well.

Best,
jeremy

On Jul 31, 2006, at 10:20 AM, Joerg D. wrote:

Now, it’s a little unclear to me how to further configure the
routes to
allow me to add the following URLs:

I need a URL to choose a file to upload, so I need an HTML ‘frontend’
for it, so I figured the following URL fits into the REST/CRUD
paradigm:

/people;bulk_import (using a GET method)

GET /people;upload

map.resource :person, :collection => { :upload => :get, :import
=> :post }

class PeopleController < ApplicationController
# Html form to upload CSV file.
def upload
end

 # Handle CSV file upload.
 def import
   Person.create(csv_to_array_of_person_hashes(params[:csv].read)
 end

end

To take it a bit further, register the CSV MIME type

register Mime::CSV as ‘text/csv’ with synonym ‘text/c-s-v’

Mime::Type.register :csv, ‘text/csv’, [‘text/comma-separated-values’]

so you can respond_to csv in index, show, etc

respond_to do |wants|
wants.html # render the rhtml template
wants.csv { render :text => person.to_csv }
end

and automatically parse CSV request bodies into @params

ActionController::Base.param_parsers[Mime::CSV] = Proc.new do |data|
# return a params hash from the csv data (better have a header
row…)
csv_to_person_hash(data)
end

so you can create and update with CSV as well.

Best,
jeremy

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs