Restful Best Practices

Post on 19-Jan-2015

2.966 views 0 download

Tags:

description

These are the slides of our talk at Fosdem 2008 (http://fosdem.org).We explain what REST is, how it is used in Rails, and finally we give some tips on how to architecture your application so that it follows the REST philosophy.

Transcript of Restful Best Practices

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