Presentation is loading. Please wait.

Presentation is loading. Please wait.

Routes & REST & URL-helpers & validations & filters

Similar presentations


Presentation on theme: "Routes & REST & URL-helpers & validations & filters"— Presentation transcript:

1 Routes & REST & URL-helpers & validations & filters
CS 98-10/CS Web 2.0 Programming Using Ruby on Rails Armando Fox

2 Administrivia Office hours switched (again...sorry)
Tuesdays 1:30-2:30 in 413 Soda Monday: Project brainstorming Weds: Project groups informally chosen-up By following Monday: start planning your app (user stories, testing, deployment....) Technical material: Routes & REST (today), more on controllers & views

3 Outline... Routing basics: how do.... REST and RESTful routes
URLs get mapped to a controller and action? link_to, redirect_to etc. generate their URLs? REST and RESTful routes what is RESTful resource access? how Rails 2.0 routing supports REST URL helpers generating URL’s (for your pages) that will map to specific controller actions...RESTfully Further reading “Rails Way” book has good content on this “Agile” book has routes, but not 2.0 routes and REST Model validations, callbacks, controller filters

4 $APP_ROOT/config/routes.rb Ruby code (that makes use of high-level methods!) to declare “rules” for mapping incoming URLs to controllers/actions actually each rule has 2 purposes: map incoming URL to ctrler/action/params generate URL to match ctrler/action/params e.g. when using link_to, redirect_to, etc. What’s in a rule? A URL template Keywords stating what to do

5 Simple example In routes.rb: In one of your views:
map.connect 'professors/:dept', :controller => 'professors', :action => 'list' In one of your views: <%= link_to "List professors in EECS", :controller => 'professors', :action => 'list', :dept => 'eecs', :hired_since => %> matching is determined by keywords link_to uses underlying function url_for, which consults routing rules to build the URL:

6 Simple example cont. Now if someone visits this URL: In routes.rb:
map.connect 'professors/:dept', :controller => 'professors', :action => 'list' Now if someone visits this URL: Matching is determined by position How about:

7 Default routes URL is compared to routing rules, one at a time, until match found then “wildcard” pieces of URL get put into params[] If no match, default route (last one in routes.rb) is used typically something like: map.connect ':controller/:action/:id' e.g., catches things like professors/edit/35 Warning! Can lead to dangerous behaviors Use the root route to map the “empty” URL (e.g. map.root :controller=>'main', :action=>'index'

8 More on Routes Ordering of routes matters; more specific ones should come earlier so they’ll match first map.connect 'users/:action/:id' map.connect ':controller/:action/:id' Many, many apps will never need to use more than the “conventional” predefined routes If you want to, you should definitely read more about routes offline

9 REST is CRUD REST Idea: each HTTP interaction should specify, on its own, a CRUD operation and which object to do it on. GET used for read operations; POST for writes (create, update, delete) Also guards against spidering/bots! Rails 2.0: routes, scaffolds and URL helpers are now all RESTful by default result: syntax of link_to, etc. has changed Get them by saying map.resources :model

10 REST and URI’s HTTP method Old style URL New (RESTful) style URL
Action & named route method to pass to url_for HTTP method Old style URL New (RESTful) style URL show: GET /:ctrl/show/:id /:ctrl/:id index (list): students_url /:ctrl/list (or /:ctrl/index) /:ctrl new: new_student_url /:ctrl/new create: students_url POST /:ctrl/create (why no ID?) destroy: DELETE /:ctrl/destroy/:id /:ctrl (but see Hack!) edit: /:ctrl/edit/:id /:ctrl/:id/edit update: PUT /:ctrl/update/:id

11 The DELETE & PUT hack REST says: use HTTP method DELETE to request deletion; PUT to request Update But: Web browsers only have GET and POST “Solution”: use POST, but include extra field _method with value DELETE or PUT routing takes care of parsing this out to disambiguate dispatching done with JavaScript in link_to (but you shouldn’t be using link_to for this...why?) or use button_to which creates a self-contained form for a single button

12 How url_for has changed
Excerpted from REST Cheat Sheet which I’m trying to get a site license for (Peepcode) Note use of either _path or _url suffix

13 That whole thing with respond_to do |format|
Let’s make it easier to read by: put the if...else outside the do block change variable name format to wants

14 Easier-to-read version
respond_to accepts a block, and yields to it passing the wants object wants’s instance methods named for possible MIME output types (HTML, XML, etc.) Each of those methods takes a block that specifies what to do for each format Based on parsing HTTP headers from request Many, many MIME types predefined (add more in environment.rb) A useful one when we do AJAX: js (runs .rjs template if available)

15 What about redirect_to?
RESTful routing strikes again! url_for and friends now assume RESTful routes by default Hint: consider Or etc.

16 Nested routes Consider a Course that belongs_to :professor (and as well, Professor has_many :courses) In particular, it makes no sense to have a course without a professor in our app, I mean When invoking CRUD methods on a course, we’d like to be able to specify which professor it belongs_to

17 Enter nested RESTful routes
map.resources :professors do |p| p.resources :courses end —or— map.resources :professors, :has_many=>:courses Now you can say course_path(:professor_id=>3, :id=>20) and get a RESTful URI for course ID 20 that belongs to professor ID 3. Note! The route builder doesn’t check if the belongs_to relationship keys match what’s in the database!

18 In Courses controller... Need to set up that owns the course in each of the methods Otherwise the URL-builder methods won’t know what the parent object ID is Ugly (we’ll learn a better way with filters): def index @professor = Professor.find(params[:professor_id]) @courses ...etc... end def update ...if update of Course fails...

19 What about views for nested models?
# example: views/courses/edit.html.erb <% do |f| %> <%= f.text :description %> <%= f.text :ccn %> <%= f.submit "Save Changes" %> <% end %> <%= link_to "Show", %> or... link_to "Show", if makes sense <%= link_to "Back", %>

20 In your index (list) view...
do |c| %> <tr> <td> c.name </td> <td><%= link_to %> </td> <td><%= link_to <td> <%= button_to "Destroy", %></td> </tr> <% end %> Similarly for other views

21 Worth understanding... Routing and REST caused lots of changes in 2.0, but ultimately they will make life better Best tutorial we’ve found (thx Arthur!): (Linked from course home page)

22 Controller predicates: verify
A declarative way to assert various preconditions on calling controller methods You can check selectively (:only, :except) for: HTTP request type (GET, POST, Ajax XHR) Presence of a key in the flash or the session Presence of a key in params[] And if the check fails, you can... redirect_to somewhere else add_to_flash a helpful message Example: verify :method => :post, :only => 'dangerous_action', :redirect_to => {:action => 'index'}, :add_to_flash => "Dangerous action requires Post"

23 More General Filters Code blocks that can go before, after or around controller actions; return Boolean before_filter :filter_method_name before_filter { |controller| ... } before_filter ClassName options include :only,:except, etc. multiple filters allowed; calls provided to prepend or append to filter chain subclasses inherit filters but can use skip_filter methods to selectively disable them If any before-filter returns false, chain halted & controller action method won’t be invoked so filter should redirect_to, render, or otherwise deal with the request Simple useful example: a before-filter for nested routes! before_filter :load_professor def load_professor @professor = Professor.find(params[:professor_id]) end

24 A General Pattern: “Do It Declaratively”
More and more ways to specify what should be done rather than how to do it Should always be asking yourself this question Especially when you find yourself (re)writing common code in multiple places!


Download ppt "Routes & REST & URL-helpers & validations & filters"

Similar presentations


Ads by Google