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 -- Posted via http://www.ruby-forum.com/.
Joerg Diekmann 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 -- Posted via http://www.ruby-forum.com/.
On Jul 31, 2006, at 10:20 AM, Joerg Diekmann 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
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 Kemper wrote:> On Jul 31, 2006, at 10:20 AM, Joerg Diekmann 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-- Posted via http://www.ruby-forum.com/.