advanced restful rails
Post on 11-Sep-2014
33 views
DESCRIPTION
Ben Scofield's session on REST and Rails at Railsconf 2008TRANSCRIPT
Advanced RESTful RailsBen Scofield
Constraints
Shall I compare thee to a summer's day?Thou art more lovely and more temperate.Rough winds do shake the darling buds of May,And summer's lease hath all too short a date.Sometime too hot the eye of heaven shines,And often is his gold complexion dimm'd;And every fair from fair some time declines,By chance, or nature's changing course, untrimm'd;But thy eternal summer shall not fade...
app controllers helpers models viewsconfig environments initializersdbdoclib taskslogpublic images javascripts stylesheetsscript performance processtest fixtures functional integration unit...
exists app/models/ exists app/controllers/ exists app/helpers/ create app/views/users exists test/functional/ exists test/unit/dependency model exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/user.rb create test/unit/user_test.rb create test/fixtures/users.yml create db/migrate create db/migrate/20080531002035_create_users.rb create app/controllers/users_controller.rb create test/functional/users_controller_test.rb create app/helpers/users_helper.rb route map.resources :users
REST
Audience Participation!who is building restful applications?
212,000 Results
How do I handle ...
Difficulteven for the pros
class UsersController < ApplicationController # ...
def activate self.current_user = params[:activation_code].blank? ? false : # ... if logged_in? && !current_user.active? current_user.activate! flash[:notice] = "Signup complete!" end redirect_back_or_default('/') end
def suspend @user.suspend! redirect_to users_path end
def unsuspend @user.unsuspend! redirect_to users_path end
def destroy @user.delete! redirect_to users_path end
def purge @user.destroy redirect_to users_path endendRestful Authentication
What is REST?
Resources
hey-helen - flickr
Addressability
memestate - flickr
Representations
stevedave - flickr
Stateless*
http://www1.ncdc.noaa.gov/pub/data/images/usa-avhrr.gif
Audience Participation!why care?
Process
tiptoe - flickr
Domain
ejpphoto - flickr
Modeled
kerim - flickr
?
Identifyresources
Selectmethods to expose
Respectthe middleman
Simple
My Pull List
Releases
class ItemsController < ApplicationController # release listing page; filters on year/month/day from params def index; endend
ActionController::Routing::Routes.draw do |map| map.releases 'releases/:year/:month/:day', :controller => 'items', :action => 'index'end
Issues
class IssuesController < ApplicationController # issue detail page def show; endend
ActionController::Routing::Routes.draw do |map| map.resources :issuesend
Series
class TitlesController < ApplicationController # title detail page def show; endend
ActionController::Routing::Routes.draw do |map| map.resources :titlesend
class IssuesController < ApplicationController # issue listing page; could be series page def index; endend
ActionController::Routing::Routes.draw do |map| map.resources :titles, :has_many => [:issues]end
Users
class UsersController < ApplicationController before_filter :require_login, :only => [:edit, :update]
# edit account def edit; end
# update account def update; endend
ActionController::Routing::Routes.draw do |map| map.resources :usersend
Lists
class UsersController < ApplicationController # public view - pull list def show; endend
ActionController::Routing::Routes.draw do |map| map.resources :usersend
class TitlesController < ApplicationController # public view - pull list, given a user_id def index; endend
ActionController::Routing::Routes.draw do |map| map.resources :users, :has_many => [:titles]end
Advanced
Login*mc - flickr
class SessionsController < ApplicationController # login form def new; end
# login action def create; end
# logout action def destroy; endend
ActionController::Routing::Routes.draw do |map| map.resource :sessionend
Homepageseandreilinger - flickr
class HomepagesController < ApplicationController # homepage def show; endend
ActionController::Routing::Routes.draw do |map| map.resource :homepage map.root :homepageend
class ContentsController < ApplicationController # static content def show # code to find a template named according to params[:page] endend
ActionController::Routing::Routes.draw do |map| map.resources :contents map.root :controller => ‘contents’, :action => ‘show’, :page => ‘homepage’end
class AdsController < ApplicationController # ad index - the million dollar homepage def index; endend
ActionController::Routing::Routes.draw do |map| map.resources :ads map.root :adsend
Dashboardhel2005 - flickr
class DashboardsController < ApplicationController before_filter :require_login
# dashboard def show; endend
ActionController::Routing::Routes.draw do |map| map.resource :dashboardend
class InstrumentsController < ApplicationController before_filter :require_login
# dashboard def index @instruments = current_user.instruments endend
ActionController::Routing::Routes.draw do |map| map.resources :instrumentsend
Previewashoe - flickr
class PreviewsController < ApplicationController def create @post = Post.find(params[:post_id]) @post.attributes = params[:post]
render :template => 'posts/show' endend
ActionController::Routing::Routes.draw do |map| map.resources :posts, :has_one => [:preview]end
class PreviewsController < ApplicationController def create @post = Post.new(params[:post])
render :template => 'posts/show' endend
ActionController::Routing::Routes.draw do |map| map.resources :posts map.resource :previewend
Searchseandreilinger - flickr
class PostsController < ApplicationController def index if params[:query].blank? @posts = Post.find(:all) else @posts = Post.find_for_query(params[:query]) end endend
ActionController::Routing::Routes.draw do |map| map.resources :postsend
class SearchesController < ApplicationController def show @results = Searcher.find(params[:query]) endend
ActionController::Routing::Routes.draw do |map| map.resource :searchend
Wizardsdunechaser - flickr
/galleries/new
/restaurants/:id/photos/new
/restaurants/:id/photos/edit
ActionController::Routing::Routes.draw do |map| map.resources :galleries map.resources :galleries map.resources :restaurants, :has_many => [:photos]
map.with_options :controller => 'photos' do |p| p.edit_restaurant_photos 'restaurants/:restaurant_id/photos/edit', :action => 'edit' p.update_restaurant_photos 'restaurants/:restaurant_id/photos/update', :action => 'update', :conditions => {:method => :put} endend
Collectionswooandy - flickr
Web Servicesjosefstuefer - flickr
Text
Inventory
Staff Directory
HR
etc.
RESTful APISearch Application
Text
Inventory
Staff Directory
HR
etc.
RESTful API
RESTful API
RESTful API
RESTful API
Search Application
Administration
this slide left intentionally blank
ActionController::Routing::Routes.draw do |map| map.namespace :admin do |admin| admin.resources :invitations admin.resources :emails admin.resources :users admin.resources :features endend
Audience Participation!what gives you fits?
Rails, Specifically
<a href="/records/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete</a>
<%= link_to 'Delete', record, :method => 'delete', :confirm => 'Are you sure?' %>
Accessibility
ActionController::Routing::Routes.draw do |map| map.users 'users', :controller => ‘users’, :action => ‘index’ map.users 'users', :controller => ‘users’, :action => ‘create’ end
Hand-Written Routes
ActionController::Routing::Routes.draw do |map| map.resources :users # Install the default route as the lowest priority. map.connect ':controller/:action/:id' end
Default Routing
Collectionswooandy - flickr
class RecordsController < ApplicationController def index; end
def show; end
# ...end
Mixed
ActionController::Routing::Routes.draw do |map| map.resources :recordsend
Separated
ActionController::Routing::Routes.draw do |map| map.resource :record_list map.resources :recordsend
class RecordListsController < ApplicationController def show; end
# ...end
class RecordsController < ApplicationController def show; end
# ...end
Audience Participation!where’s rails bitten you?
Thanks!ben [email protected]://www.viget.com/extendhttp://www.culann.com
☜