restful best practices
DESCRIPTION
Best practices when designing a RESTful web application. Presented at the Ruby and Rails devroom at FOSDEM 2008.TRANSCRIPT
RESTful best practicesJean-Baptiste Escoyez & Nicolas Jacobeus
FOSDEM ’08 Ruby on Rails DevRoom24 February 2008
Frailers.net
Outline
REST
REST in Rails
REST in Rails: Best practices
REST
REST
What is REST?
How does REST work?
Why REST?
REST
What is REST?
It’s about communication between computers
It’s about designing the architecture of your applications
REST » What is REST?
It’s about communication between computers
Web services!
SOAP / XML-RPC => communication
REST => communication + standardisation
REST » What is REST?
It’s about architecturing your application
esis by Roy Fielding (2000)“Architectural Styles and the Design of Network-based Software Architectures”
REST applies some constraints to the architecture of your application
e interface is the same for humans and computers
(by the way: REST means Representational State Transfer... I think)
REST » What is REST?
How does REST work ?
Everything is a “resource”
4 basic requirements for a RESTful system
REST » How does REST work?
e concept of resource
Resource = thing exposed by the system to the outside world
Everything is a resourcehttp://www.frailers.net/users/1http://www.frailers.net/users/1/memberships
Independent from its representationuser.html => http://www.frailers.net/users/1user.jpg => http://www.frailers.net/users/1
REST » How does REST work?
When is a system RESTful ?
Addressability
Statelessness
Connectivity
Uniform interface
4 standardized actions: GET - POST - PUT - DELETE
Safety (GET)
Idempotence (PUT-DELETE)
REST » How does REST work?
So, why REST ?
Standardisation is good
Why use so many different functions when you always do the same (CRUD’ing objects)
Why separate the logic for computers and humans ? (segregation is evil)
Statelessness => scalability and decoupling
REST » Why REST?
Enough for this theoretical HTTP stuff!
is is a DevRoom about , right ?
REST » Why REST?
REST in Rails
(Not on Rails !)
REST in Rails
Addressability: RESTful routes
Representation independence: respond_to
Nesting resources
Developing REST clients
...and some tasty Rails sugars
REST in Rails
Addressability : Routes
REST in Rails » Routes
RESTless RESTfulVERB HREF VERB URIPOST /users/create POST /users
GET /users/1 GET /users/1
POST /users/1/update PUT /users/1
???? /users/1/delete DELETE /users/1
Addressability : Routes
REST in Rails » Routes
map.resources :usersResource Verb Action
/users GET index/users POST create
/users/1 GET show/users/1 PUT update/users/1 DELETE destroy
RESTful Rails controller
A RESTful controller has 7 standard actions
Each controller deals with a resource (user) and its collection (list of users)
REST in Rails » Routes
Representation independence: respond_to
Based on:
HTTP Accept Header
Format extensionhttp://www.frailers.net/articles/24/comments/1.htmlhttp://www.frailers.net/articles/24/comments/1.js
REST in Rails » respond_to
Making REST clients : ActiveResource
class Project < ActiveResource::Base self.site = “http://localhost:3000”end
projects = Project.find(:all)new_project = Project.new(:name => “My new project”)new_project.save
REST in Rails » ActiveResource
Nested resourceshttp://www.frailers.net/articles/24/comments/1http://www.frailers.net/articles/24/author
ActionController::Routing::Routes.draw do |map| map.resources :articles do |article| article.resources :comments article.resource :author endend
REST in Rails » Nested resources
More rails sugars
Scaffolding
script/generate scaffold article title:string \ body:text published:boolean
Helperslink_to @articleform_for @comment do |f| ... endredirect_to @article
AuthenticationRESTful authentication plugin
REST in Rails » Sugars
To sum up...
Using REST in Rails is good
lightweight controllers
API given for free
Rails is opinionated
implementation of REST is not perfect
REST in Rails » Conclusion
Best practices
Best practices
Design methodology
Real-life examples
Best Practices
Disclaimer!
Maybe “best” is an overstatement(is sounded great for the call for papers)
ere are always different solutions
Best Practices » Disclaimer
Design methodology
Knowing Rails’ resources API is great, but not sufficient
e big question:
what resources do I choose ?
Best Practices » Design methodology
Classic beginner’s mistakes
strictly mirroring your ActiveRecord data model to choose your resources
thinking all 7 actions should be written for each and every resource
and, of course, adding custom methods if the standard ones don’t fit
Best Practices » Design methodology
Resources are not models
Well, to be fair, then can (and usually) represent models
But also:RelationsStatesEvents(DHH told me so)
Best Practices » Design methodology
Nouns are the new verbs
Change your way of explaining a scenario, an action
Use a noun to describe the action
e noun given to your scenario is the resource you’re looking for
A user subscribes to a group A subscription is created
e project is validated by its owner A project validation is created
e user deactivates his account A user account activation is deleted
Best Practices » Design methodology
7 is not a strict target
Resources can be read-only
Sometimes, actions aremeaningless:
update an “account activation” ? really ?
destroy a “page view” ? why ?
Best Practices » Design methodology
Don’t be tempted!
Rails allows extra, custom methods to be added to controllers, if you really need them
But you’ll lose all what you were trying to do in the first place (no uniform interface, etc.)
I have never needed that (except, maybe...)
If you do need that, it’s probable that you’d better rethink your architecture
Best Practices » Design methodology
OK, you want real-life examples
Adding/removing members from a group
Dealing with object workflows
Multi-step edition wizard
Managing a shopping cart
Manipulating several resource in one request
Best Practices » Real-life examples
Adding / Removing members from a group
Best Practices » Real-life examples
Adding / Removing members from a group
Best Practices » Real-life examples
Dealing with object workflows
Consider a CMS withall sorts of documents
Each document has a status: draft, reviewed,published, ...
Best Practices » Real-life examples
Dealing with object workflows
Or another way : only “update” the document
depending on the business logic, this can be considered overloading
Best Practices » Real-life examples
Multi-step edition wizard
A complex model needs tobe edited in 3 steps, in aprecise order
Best Practices » Real-life examples
Multi-step edition wizard
All these steps are different, partial representations of the same resource
Just GET the resource and put the step as a parameter
Update the resource at each step... and redirect to the next step representation
Best Practices » Real-life examples
Multi-step edition wizard
Best Practices » Real-life examples
Managing a shopping cart
We keep in the database the state of the shopping cart for each user:/users/21/shopping_cart_items
Yes, but I don’t want the cart to be persistentDelete from the database when the user logs out
Best Practices » Real-life examples
Manipulating two resources simultaneously
You’re not manipulating two resources
You’re manipulating a couple of things
e resource is the couple
Create guy, create girl => Create couple
Best Practices » Real-life examples
Manipulating two resources simultaneously
If you still need to do it inseveral steps...
CREATE a Transaction resource
PUT the first part
PUT the second part
commit (PUT “committed”)or revert (DELETE)
Best Practices » Real-life examples
ere are still some limitations...
I want to choose items to delete from a list with checkboxes
DELETE only works for a single resource at a time
What you’re doing is updating the parent resource
If there’s no parent resource, you’re screwed
Best Practices » Real-life examples
ank you!
It’s lunch time!
Let’s eat!
Let’s create some LunchEatings !
POST /lunch_eatings