0% found this document useful (0 votes)
766 views

Advanced RESTful Rails

One of the big benefits of Rails is that it standardizes application development in a way you don’t see with many of the alternatives. That has made Rails applications easier and faster to develop, and much easier to maintain, than competing frameworks. This isn’t just a one-time benefit, however; with the integration of RESTful principles over the last two years, Rails applications have become even more standardized. Developers of RESTful applications can see as much of an improvement over other Rails applications as they originally saw over their old (say, PHP) sites. This benefit, however, is not without a downside. While REST is easy to follow in the most common cases, it can be difficult to apply to some scenarios – the classic question being how to represent search RESTfully. This new approach to domain modeling can get complicated, as even one of the paradigmatic examples of RESTful Rails, the restful_authentication plugin, shows – it abandons the principles when it comes to activation. The difficulties of RESTful Rails don’t end with domain modeling, however; problems also arise from the implementation of REST in Rails. For instance, the standard approach to deleting a resource (link_to with method delete) is wholly inaccessible to anyone with JavaScript disabled. In this session, we’ll take a look at these (and other) issues that you may encounter when you start building things outside the standard examples. From modeling complicated domains (authentication, search, and beyond), to working around the implementation of REST in Rails, we’ll discuss and apply techniques that you’ll find useful for every RESTful application you develop in the future.

Uploaded by

Dmytro Shteflyuk
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
766 views

Advanced RESTful Rails

One of the big benefits of Rails is that it standardizes application development in a way you don’t see with many of the alternatives. That has made Rails applications easier and faster to develop, and much easier to maintain, than competing frameworks. This isn’t just a one-time benefit, however; with the integration of RESTful principles over the last two years, Rails applications have become even more standardized. Developers of RESTful applications can see as much of an improvement over other Rails applications as they originally saw over their old (say, PHP) sites. This benefit, however, is not without a downside. While REST is easy to follow in the most common cases, it can be difficult to apply to some scenarios – the classic question being how to represent search RESTfully. This new approach to domain modeling can get complicated, as even one of the paradigmatic examples of RESTful Rails, the restful_authentication plugin, shows – it abandons the principles when it comes to activation. The difficulties of RESTful Rails don’t end with domain modeling, however; problems also arise from the implementation of REST in Rails. For instance, the standard approach to deleting a resource (link_to with method delete) is wholly inaccessible to anyone with JavaScript disabled. In this session, we’ll take a look at these (and other) issues that you may encounter when you start building things outside the standard examples. From modeling complicated domains (authentication, search, and beyond), to working around the implementation of REST in Rails, we’ll discuss and apply techniques that you’ll find useful for every RESTful application you develop in the future.

Uploaded by

Dmytro Shteflyuk
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 78

Advanced RESTful Rails

Ben 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
views
config
environments
initializers
db
doc
lib
tasks
log
public
images
javascripts
stylesheets
script
performance
process
test
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 ...
Difficult
even 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

Restful Authentication
end
end
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
?
Identify
resources
Select
methods to expose
Respect
the middleman
Simple
My Pull List
Releases
ActionController::Routing::Routes.draw do |map|
map.releases 'releases/:year/:month/:day',
:controller => 'items', :action => 'index'
end

class ItemsController < ApplicationController


# release listing page; filters on year/month/day from params
def index; end
end
Issues
ActionController::Routing::Routes.draw do |map|
map.resources :issues
end

class IssuesController < ApplicationController


# issue detail page
def show; end
end
Series
ActionController::Routing::Routes.draw do |map|
map.resources :titles
end

class TitlesController < ApplicationController


# title detail page
def show; end
end
ActionController::Routing::Routes.draw do |map|
map.resources :titles, :has_many => [:issues]
end

class IssuesController < ApplicationController


# issue listing page; could be series page
def index; end
end
Users
ActionController::Routing::Routes.draw do |map|
map.resources :users
end

class UsersController < ApplicationController


before_filter :require_login, :only => [:edit, :update]

# edit account
def edit; end

# update account
def update; end
end
Lists
ActionController::Routing::Routes.draw do |map|
map.resources :users
end

class UsersController < ApplicationController


# public view - pull list
def show; end
end
ActionController::Routing::Routes.draw do |map|
map.resources :users, :has_many => [:titles]
end

class TitlesController < ApplicationController


# public view - pull list, given a user_id
def index; end
end
Advanced
Login* mc - flickr
ActionController::Routing::Routes.draw do |map|
map.resource :session
end

class SessionsController < ApplicationController


# login form
def new; end

# login action
def create; end

# logout action
def destroy; end
end
Homepage seandreilinger - flickr
ActionController::Routing::Routes.draw do |map|
map.resource :homepage
map.root :homepage
end

class HomepagesController < ApplicationController


# homepage
def show; end
end
ActionController::Routing::Routes.draw do |map|
map.resources :contents
map.root :controller => ‘contents’, :action => ‘show’,
:page => ‘homepage’
end

class ContentsController < ApplicationController


# static content
def show
# code to find a template named according to params[:page]
end
end
ActionController::Routing::Routes.draw do |map|
map.resources :ads
map.root :ads
end

class AdsController < ApplicationController


# ad index - the million dollar homepage
def index; end
end
Dashboard hel2005 - flickr
ActionController::Routing::Routes.draw do |map|
map.resource :dashboard
end

class DashboardsController < ApplicationController


before_filter :require_login

# dashboard
def show; end
end
ActionController::Routing::Routes.draw do |map|
map.resources :instruments
end

class InstrumentsController < ApplicationController


before_filter :require_login

# dashboard
def index
@instruments = current_user.instruments
end
end
Preview ashoe - flickr
ActionController::Routing::Routes.draw do |map|
map.resources :posts, :has_one => [:preview]
end

class PreviewsController < ApplicationController


def create
@post = Post.find(params[:post_id])
@post.attributes = params[:post]

render :template => 'posts/show'


end
end
ActionController::Routing::Routes.draw do |map|
map.resources :posts
map.resource :preview
end

class PreviewsController < ApplicationController


def create
@post = Post.new(params[:post])

render :template => 'posts/show'


end
end
Search seandreilinger - flickr
ActionController::Routing::Routes.draw do |map|
map.resources :posts
end

class PostsController < ApplicationController


def index
if params[:query].blank?
@posts = Post.find(:all)
else
@posts = Post.find_for_query(params[:query])
end
end
end
ActionController::Routing::Routes.draw do |map|
map.resource :search
end

class SearchesController < ApplicationController


def show
@results = Searcher.find(params[:query])
end
end
Wizards dunechaser - 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}
end
end
Collections wooandy - flickr
Web Services josefstuefer - flickr
Staff Directory

Inventory
Search Application Text
RESTful API
HR

etc.
RESTful API Staff Directory

RESTful API Inventory


Search Application Text
RESTful API HR

RESTful API etc.


this slide left intentionally blank

Administration
ActionController::Routing::Routes.draw do |map|
map.namespace :admin do |admin|
admin.resources :invitations
admin.resources :emails
admin.resources :users
admin.resources :features
end
end
Audience Participation!
what gives you fits?
Rails, Specifically
<%= link_to 'Delete', record, :method => 'delete',
:confirm => 'Are you sure?' %>

<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>

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
Collections wooandy - flickr
ActionController::Routing::Routes.draw do |map|
map.resources :records
end

class RecordsController < ApplicationController


def index; end

def show; end

# ...
end

Mixed
ActionController::Routing::Routes.draw do |map|
map.resource :record_list
map.resources :records
end

class RecordListsController < ApplicationController


def show; end

# ...
end

class RecordsController < ApplicationController


def show; end

# ...
end

Separated
Audience Participation!
where’s rails bitten you?
Thanks!
ben scofield
[email protected]
http://www.viget.com/extend
http://www.culann.com

You might also like