Fearless Fool
2010-Apr-30 19:57 UTC
controller methods and how I learned to love ''rake routes''
Face it: to the newcomer, Rails routing is strange and mysterious. It took me a while get the hang of it, so I thought I''d share some info (and a couple of handy techniques) for those who are new to Rails. Here, assume we have Users and Reports, and that one User "has many" Reports. Normally, that will be expressed in your model files (but that''s another topic!) -- but right now we''re focused on making an entry in config/routes.rb to express how incoming URLs map to your controllers. In this example, we''re using RESTful routing to create "shallow nested routes" to express that a User :has_many Reports. So we create an entry in config/routes.rb like this: ====== config/routes.rb: map.resources :users, :has_many => :reports, :shallow => true ===== Assuming we already have a controller for User, we still need a controller for Reports. Go ahead and type "rake routes" in a shell window to see what the routing system generated. Here are the relevant lines for the Reports controller: =====% rake routes ... user_reports GET /users/:user_id/reports {:controller=>"reports", :action=>"index"} POST /users/:user_id/reports {:controller=>"reports", :action=>"create"} new_user_report GET /users/:user_id/reports/new {:controller=>"reports", :action=>"new"} edit_report GET /reports/:id/edit {:controller=>"reports", :action=>"edit"} report GET /reports/:id {:controller=>"reports", :action=>"show"} PUT /reports/:id {:controller=>"reports", :action=>"update"} DELETE /reports/:id {:controller=>"reports", :action=>"destroy"} ... ===== Though it may not be immediately obvious, each line tells us two things: which URL will be matched to method in the Reports controller, and a ''helper function'' you can use to generate that URL. The leftmost column is the name of the helper functions that have been created for you, but stripped of _url or _path, so ''user_reports'' signifies ''user_reports_url(user_id)'' (the fully qualified url) or ''user_repors_path(user_id)'' (the abbreviated path). The next column is the HTTP method (GET, POST, PUT, DELETE). The third column is the path template that the routing system matches against: the incoming URL must have this form to be a match. And the last column is the controller and method within the controller that gets called for that method/template combination. Handy technique 1: ================= To better understand those generated helper functions, launch a console. Within the console, you can test the helper functions using ''app.<helper_fn>'' like this: =====bash-3.2$ script/console Loading development environment (Rails 2.3.5)>> app.user_reports_path(10)=> "/users/10/reports">> app.user_reports_url(10)=> "http://www.example.com/users/10/reports">> app.new_user_report_path(10)=> "/users/10/reports/new">> app.edit_report_url(33)=> "http://www.example.com/reports/33/edit">> app.report_path(33)=> "/reports/33" ===== Handy technique 2: ================= Since I haven''t been writing Rails code very long I can''t keep all these routes, parameters and helper functions straight in my mind. So the first thing I do is stub out a skeleton ReportsController and annotate with comments lifted from ''rake routes''. Here''s what my skeleton ReportsController might look like -- the comment before each method documents the helper function that will generate the HTTP call to get you to that method, and what to look for in your params[] hash. If you look at the comments, the relationship to the output of rake routes should be obvious. (It would be great if ''script/generate controller'' added these comments for your automatically! That will be a future project unless someone beats me to it...) ====== file: app/controllers/reports_controller.rb class ReportsController < ApplicationController # arrive here via ''GET user_reports_{url|path}(user_id)'' # url has the form ''/users/:user_id/reports'' def index end # arrive here via ''POST user_reports_{url|path}(user_id)'' # url has the form ''/users/:user_id/reports'' def create end # arrive here via ''GET new_user_report_{url|path}(user_id)'' # url has the form ''/users/:user_id/reports/new'' def new end # arrive here via ''GET edit_report_{url|path}(id)'' # url has the form ''/reports/:id/edit'' def edit end # arrive here via ''GET report_{url|path}(id)'' # url has the form ''/reports/:id'' def show end # arrive here via ''PUT report_{url|path}(id)'' # url has the form ''/reports/:id'' def update end # arrive here via ''DELETE report_{url|path}(id)'' # url has the form ''/reports/:id'' def destroy end end =====So now, you can fill out your code knowing what you''ll find in the params hash when a method is called, and which helper function will generate an HTTP call to each method within your controller. Hope this helps. - ff -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.