220
Making Rails really Restful Improving the world of Resources on Rails with Restfulie Fabio Akita - akitaonrails.com - @akitaonrails Wednesday, June 9, 2010

Making Rails Really restful

Embed Size (px)

Citation preview

Page 1: Making Rails Really restful

Making Rails really RestfulImproving the world of Resources on Rails with Restfulie

Fabio Akita - akitaonrails.com - @akitaonrails

Wednesday, June 9, 2010

Page 2: Making Rails Really restful

The greatest thing about talking to you

Wednesday, June 9, 2010

Page 3: Making Rails Really restful

We’ve been through this already!

Wednesday, June 9, 2010

Page 4: Making Rails Really restful

We’ve been through this already!

No WSDL and WS-*

Wednesday, June 9, 2010

Page 5: Making Rails Really restful

We’ve been through this already!

No WSDL and WS-*No XML-RPC

Wednesday, June 9, 2010

Page 6: Making Rails Really restful

We’ve been through this already!

No WSDL and WS-*No XML-RPC

No $$ enterprisey stuff

Wednesday, June 9, 2010

Page 7: Making Rails Really restful

We’ve been through this already!

No WSDL and WS-*No XML-RPC

No $$ enterprisey stuff

♥ HTTP

Wednesday, June 9, 2010

Page 8: Making Rails Really restful

♥ HTTP

Wednesday, June 9, 2010

Page 9: Making Rails Really restful

♥ HTTP

Shared Nothing Architecture

Wednesday, June 9, 2010

Page 10: Making Rails Really restful

♥ HTTP

Shared Nothing ArchitectureStateless

Wednesday, June 9, 2010

Page 11: Making Rails Really restful

♥ HTTP

Shared Nothing ArchitectureStateless

Caching

Wednesday, June 9, 2010

Page 12: Making Rails Really restful

♥ HTTP

Shared Nothing ArchitectureStateless

CachingProxies and Reverse Proxies

Wednesday, June 9, 2010

Page 13: Making Rails Really restful

♥ HTTP

Shared Nothing ArchitectureStateless

CachingProxies and Reverse Proxies

Wednesday, June 9, 2010

Page 14: Making Rails Really restful

Discovering a world of

Resources on RailsDavid Heinemeir Hansson RailsConf 2006

Wednesday, June 9, 2010

Page 15: Making Rails Really restful

Create Read Update Delete

Wednesday, June 9, 2010

Page 16: Making Rails Really restful

Wednesday, June 9, 2010

Page 17: Making Rails Really restful

GET POST PUT DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

Wednesday, June 9, 2010

Page 18: Making Rails Really restful

GET POST PUT DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

Wednesday, June 9, 2010

Page 19: Making Rails Really restful

GET POST PUT DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

Wednesday, June 9, 2010

Page 20: Making Rails Really restful

GET POST PUT DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

Wednesday, June 9, 2010

Page 21: Making Rails Really restful

POST /people/createGET /people/show/1POST /people/update/1POST /people/destroy/1

Wednesday, June 9, 2010

Page 22: Making Rails Really restful

POST /peopleGET /people/1PUT /people/1DELETE /people/1

Wednesday, June 9, 2010

Page 23: Making Rails Really restful

MyApp::Application.routes.draw do |map| resources :peopleend

Wednesday, June 9, 2010

Page 24: Making Rails Really restful

class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create end

# GET /people # GET /people.xml def show end

# PUT /people/1 # PUT /people/1.xml def update end

# DELETE /people/1 # DELETE /people/1.xml def destroy endend

form_for(@person) do |f| f.text_field :nameend

Wednesday, June 9, 2010

Page 25: Making Rails Really restful

class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create end

# GET /people # GET /people.xml def show end

# PUT /people/1 # PUT /people/1.xml def update end

# DELETE /people/1 # DELETE /people/1.xml def destroy endend

link_to 'Show', person

Wednesday, June 9, 2010

Page 26: Making Rails Really restful

class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create end

# GET /people # GET /people.xml def show end

# PUT /people/1 # PUT /people/1.xml def update end

# DELETE /people/1 # DELETE /people/1.xml def destroy endend

form_for(@person) do |f| f.text_field :nameend

Wednesday, June 9, 2010

Page 27: Making Rails Really restful

class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create end

# GET /people # GET /people.xml def show end

# PUT /people/1 # PUT /people/1.xml def update end

# DELETE /people/1 # DELETE /people/1.xml def destroy endend

link_to 'Destroy', person, :method => :delete

Wednesday, June 9, 2010

Page 28: Making Rails Really restful

Answering to mime types

Wednesday, June 9, 2010

Page 29: Making Rails Really restful

Answering to mime types

One controller for many clients

Wednesday, June 9, 2010

Page 30: Making Rails Really restful

Answering to mime types

One controller for many clientsOne action returning different representations

Wednesday, June 9, 2010

Page 31: Making Rails Really restful

Answering to mime types

One controller for many clientsOne action returning different representations

“Content Negotiation"

Wednesday, June 9, 2010

Page 32: Making Rails Really restful

class PeopleController < ApplicationController def index @people = Person.all

respond_to do |format| format.html # index.html.erb format.js # index.js.erb format.atom # index.atom.builder format.xml { render :xml => @people } end endend

Wednesday, June 9, 2010

Page 33: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

Wednesday, June 9, 2010

Page 34: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

Wednesday, June 9, 2010

Page 35: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

GET /people=> returns HTML

GET /people.xml=> returns XML

Accept: text/javascriptGET /people=> returns JS

Accept: text/xmlGET /people=> returns XML

Wednesday, June 9, 2010

Page 36: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

GET /people=> returns HTML

GET /people.xml=> returns XML

Accept: text/javascriptGET /people=> returns JS

Accept: text/xmlGET /people=> returns XML

Wednesday, June 9, 2010

Page 37: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

GET /people=> returns HTML

GET /people.xml=> returns XML

Accept: text/javascriptGET /people=> returns JS

Accept: text/xmlGET /people=> returns XML

Wednesday, June 9, 2010

Page 38: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) endend

GET /people=> returns HTML

GET /people.xml=> returns XML

Accept: text/javascriptGET /people=> returns JS

Accept: text/xmlGET /people=> returns XML

Wednesday, June 9, 2010

Page 39: Making Rails Really restful

2008Rails 2.2

Wednesday, June 9, 2010

Page 40: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

Wednesday, June 9, 2010

Page 41: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

Wednesday, June 9, 2010

Page 42: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

GET /people/1

Wednesday, June 9, 2010

Page 43: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

GET /people/1=> returns:

HTTP/1.1 200 OK Etag: "fd19b85b6ba49b5778de34310d141319"Last-Modified: Fri, 21 May 2010 05:31:11 GMTContent-Type: text/html; charset=utf-8Cache-Control: public...

Wednesday, June 9, 2010

Page 44: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

GET /people/1=> returns:

HTTP/1.1 200 OK Etag: "fd19b85b6ba49b5778de34310d141319"Last-Modified: Fri, 21 May 2010 05:31:11 GMTContent-Type: text/html; charset=utf-8Cache-Control: public...

Wednesday, June 9, 2010

Page 45: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

If-None-Match: "fd19b85b6ba49b5778de34310d141319"GET /people/1

Wednesday, June 9, 2010

Page 46: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

If-None-Match: "fd19b85b6ba49b5778de34310d141319"GET /people/1

Wednesday, June 9, 2010

Page 47: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

If-None-Match: "fd19b85b6ba49b5778de34310d141319"GET /people/1=> returns:

HTTP/1.1 304 Not Modified Etag: "fd19b85b6ba49b5778de34310d141319"Last-Modified: Fri, 21 May 2010 05:31:11 GMTCache-Control: public...

Wednesday, June 9, 2010

Page 48: Making Rails Really restful

class PeopleController < ApplicationController respond_to :html, :js, :xml def show @person = Person.find(params[:id]) if stale?(:etag => @person, :last_modified => @person.created_at.utc, :public => true) respond_with @person end endend

If-None-Match: "fd19b85b6ba49b5778de34310d141319"GET /people/1=> returns:

HTTP/1.1 304 Not Modified Etag: "fd19b85b6ba49b5778de34310d141319"Last-Modified: Fri, 21 May 2010 05:31:11 GMTCache-Control: public...

Wednesday, June 9, 2010

Page 49: Making Rails Really restful

But!

Wednesday, June 9, 2010

Page 50: Making Rails Really restful

CRUD is not a goal,it’s an aspiration,

a design technique

Wednesday, June 9, 2010

Page 51: Making Rails Really restful

And we are not done yet!

Wednesday, June 9, 2010

Page 52: Making Rails Really restful

Why not?

ConsistencySimplicity

Discoverability

Wednesday, June 9, 2010

Page 53: Making Rails Really restful

Why not?

ConsistencySimplicity

Discoverability

Wednesday, June 9, 2010

Page 54: Making Rails Really restful

Why not?

ConsistencySimplicity

Discoverability

Wednesday, June 9, 2010

Page 55: Making Rails Really restful

This is NOT necessarily REST

Wednesday, June 9, 2010

Page 56: Making Rails Really restful

This is NOT necessarily REST

Using HTTP

Wednesday, June 9, 2010

Page 57: Making Rails Really restful

This is NOT necessarily REST

Using HTTPUsing HTTP Verbs (PUT, DELETE)

Wednesday, June 9, 2010

Page 58: Making Rails Really restful

This is NOT necessarily REST

Using HTTPUsing HTTP Verbs (PUT, DELETE)

Pretty URIs

Wednesday, June 9, 2010

Page 59: Making Rails Really restful

Most of what we call “REST” is not REST

Wednesday, June 9, 2010

Page 60: Making Rails Really restful

REST Principles

Wednesday, June 9, 2010

Page 61: Making Rails Really restful

REST Principles

Identi"cation of Resources

Wednesday, June 9, 2010

Page 62: Making Rails Really restful

REST Principles

Identi"cation of ResourcesManipulate resources through representations

Wednesday, June 9, 2010

Page 63: Making Rails Really restful

REST Principles

Identi"cation of ResourcesManipulate resources through representations

Self-descriptive messages

Wednesday, June 9, 2010

Page 64: Making Rails Really restful

REST Principles

Identi"cation of ResourcesManipulate resources through representations

Self-descriptive messagesHATEOAS

Wednesday, June 9, 2010

Page 65: Making Rails Really restful

REST Goals

Wednesday, June 9, 2010

Page 66: Making Rails Really restful

REST Goals

Scalability of component interactions

Wednesday, June 9, 2010

Page 67: Making Rails Really restful

REST Goals

Scalability of component interactionsGenerality of interfaces

Wednesday, June 9, 2010

Page 68: Making Rails Really restful

REST Goals

Scalability of component interactionsGenerality of interfaces

Independent deployment of components

Wednesday, June 9, 2010

Page 69: Making Rails Really restful

REST Goals

Scalability of component interactionsGenerality of interfaces

Independent deployment of componentsReduce latency, enforce security

Wednesday, June 9, 2010

Page 70: Making Rails Really restful

REST Goals

Scalability of component interactionsGenerality of interfaces

Independent deployment of componentsReduce latency, enforce security

http://en.wikipedia.org/wiki/Representational_State_Transfer#Guiding_principles_of_a_REST_interface

Wednesday, June 9, 2010

Page 71: Making Rails Really restful

Constraints are liberating(a straight jacket for your mind)

Wednesday, June 9, 2010

Page 72: Making Rails Really restful

Wednesday, June 9, 2010

Page 73: Making Rails Really restful

What are we doing right?

Wednesday, June 9, 2010

Page 74: Making Rails Really restful

What are we doing right?

Uniform Interface (URI Templates)

Wednesday, June 9, 2010

Page 75: Making Rails Really restful

What are we doing right?

Uniform Interface (URI Templates)HTTP Verbs (some)

Wednesday, June 9, 2010

Page 76: Making Rails Really restful

What are we doing right?

Uniform Interface (URI Templates)HTTP Verbs (some)

HTTP Status Codes (some)

Wednesday, June 9, 2010

Page 77: Making Rails Really restful

What are we doing right?

Uniform Interface (URI Templates)HTTP Verbs (some)

HTTP Status Codes (some)Content Negotiation

Wednesday, June 9, 2010

Page 78: Making Rails Really restful

What is missing?

Wednesday, June 9, 2010

Page 79: Making Rails Really restful

What is missing?

More HTTP (verbs, status codes, headers)

Wednesday, June 9, 2010

Page 80: Making Rails Really restful

What is missing?

More HTTP (verbs, status codes, headers)Hyperlinks

Wednesday, June 9, 2010

Page 81: Making Rails Really restful

What is missing?

More HTTP (verbs, status codes, headers)Hyperlinks

Semantic (media-types)

Wednesday, June 9, 2010

Page 82: Making Rails Really restful

GET POST DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

PUT

Wednesday, June 9, 2010

Page 83: Making Rails Really restful

GET POST DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

POST

Wednesday, June 9, 2010

Page 84: Making Rails Really restful

GET POST DELETE

!nd create update destroy

SELECT INSERT UPDATE DELETE

PATCH

Wednesday, June 9, 2010

Page 85: Making Rails Really restful

GET POST PUT PATCH DELETE

!nd create replace update destroy

SELECT INSERT UPDATE UPDATE DELETE

RFC 5789 - http://www.innoq.com/blog/st/2010/03/rfc_5789_patch_method_for_http.html

Wednesday, June 9, 2010

Page 86: Making Rails Really restful

Why bother?

Wednesday, June 9, 2010

Page 87: Making Rails Really restful

Why bother?

Consistency

Wednesday, June 9, 2010

Page 88: Making Rails Really restful

Why bother?

ConsistencySimplicity

Wednesday, June 9, 2010

Page 89: Making Rails Really restful

Why bother?

ConsistencySimplicity

Discoverability

Wednesday, June 9, 2010

Page 90: Making Rails Really restful

Richardson Restful ModelRichardson Restful Model

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 91: Making Rails Really restful

Richardson Restful ModelRichardson Restful Model

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 92: Making Rails Really restful

Richardson Restful ModelRichardson Restful Model

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 93: Making Rails Really restful

Richardson Restful ModelRichardson Restful Model

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 94: Making Rails Really restful

The Web as it is

Wednesday, June 9, 2010

Page 95: Making Rails Really restful

The Web as it is

Wednesday, June 9, 2010

Page 96: Making Rails Really restful

Evaluation Workflow

Wednesday, June 9, 2010

Page 97: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Wednesday, June 9, 2010

Page 98: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

Wednesday, June 9, 2010

Page 99: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluated

Wednesday, June 9, 2010

Page 100: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Wednesday, June 9, 2010

Page 101: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Then approve the app

Wednesday, June 9, 2010

Page 102: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Then approve the app

When there is an app being evaluated

Wednesday, June 9, 2010

Page 103: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Then approve the app

When there is an app being evaluated

And the app doesn't pass the criteria

Wednesday, June 9, 2010

Page 104: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Then approve the app

When there is an app being evaluated

And the app doesn't pass the criteriaThen decline the app

Wednesday, June 9, 2010

Page 105: Making Rails Really restful

Wednesday, June 9, 2010

Page 106: Making Rails Really restful

Wednesday, June 9, 2010

Page 107: Making Rails Really restful

Wednesday, June 9, 2010

Page 108: Making Rails Really restful

Wednesday, June 9, 2010

Page 109: Making Rails Really restful

Wednesday, June 9, 2010

Page 110: Making Rails Really restful

Wednesday, June 9, 2010

Page 111: Making Rails Really restful

Wednesday, June 9, 2010

Page 112: Making Rails Really restful

Wednesday, June 9, 2010

Page 113: Making Rails Really restful

Wednesday, June 9, 2010

Page 114: Making Rails Really restful

Wednesday, June 9, 2010

Page 115: Making Rails Really restful

The Automated Web?

Wednesday, June 9, 2010

Page 116: Making Rails Really restful

The Automated Web?

?

Wednesday, June 9, 2010

Page 117: Making Rails Really restful

require 'rubygems'require 'mechanize'

agent = Mechanize.new { |agent| agent.user_agent_alias = "Mac Safari" }

agent.get("http://localhost:3000/apps?state=new")

Wednesday, June 9, 2010

Page 118: Making Rails Really restful

require 'rubygems'require 'mechanize'

agent = Mechanize.new { |agent| agent.user_agent_alias = "Mac Safari" }

agent.get("http://localhost:3000/apps?state=new")

Wednesday, June 9, 2010

Page 119: Making Rails Really restful

require 'rubygems'require 'mechanize'

agent = Mechanize.new { |agent| agent.user_agent_alias = "Mac Safari" }

agent.get("http://localhost:3000/apps?state=new")

Wednesday, June 9, 2010

Page 120: Making Rails Really restful

agent.click agent.page.link_with(:href => /apps\/\d+/)

evaluate = agent.page.link_with(:text => /Evaluate/)agent.post evaluate.href, "" if evaluate

approve = agent.page.link_with :text => /Approve/ decline = agent.page.link_with :text => /Decline/

Wednesday, June 9, 2010

Page 121: Making Rails Really restful

agent.click agent.page.link_with(:href => /apps\/\d+/)

evaluate = agent.page.link_with(:text => /Evaluate/)agent.post evaluate.href, "" if evaluate

approve = agent.page.link_with :text => /Approve/ decline = agent.page.link_with :text => /Decline/

Wednesday, June 9, 2010

Page 122: Making Rails Really restful

agent.click agent.page.link_with(:href => /apps\/\d+/)

evaluate = agent.page.link_with(:text => /Evaluate/)agent.post evaluate.href, "" if evaluate

approve = agent.page.link_with :text => /Approve/ decline = agent.page.link_with :text => /Decline/

Wednesday, June 9, 2010

Page 123: Making Rails Really restful

agent.click agent.page.link_with(:href => /apps\/\d+/)

evaluate = agent.page.link_with(:text => /Evaluate/)agent.post evaluate.href, "" if evaluate

approve = agent.page.link_with :text => /Approve/ decline = agent.page.link_with :text => /Decline/

Wednesday, June 9, 2010

Page 124: Making Rails Really restful

if approve && decline description = agent.page.search("pre").text

if description =~ /Flash/ agent.post decline.href, ""

elsif description =~ /sex/ agent.post decline.href, ""

else agent.post approve.href, ""

end

end

Wednesday, June 9, 2010

Page 125: Making Rails Really restful

if approve && decline description = agent.page.search("pre").text

if description =~ /Flash/ agent.post decline.href, ""

elsif description =~ /sex/ agent.post decline.href, ""

else agent.post approve.href, ""

end

end

Wednesday, June 9, 2010

Page 126: Making Rails Really restful

if approve && decline description = agent.page.search("pre").text

if description =~ /Flash/ agent.post decline.href, ""

elsif description =~ /sex/ agent.post decline.href, ""

else agent.post approve.href, ""

end

end

Wednesday, June 9, 2010

Page 127: Making Rails Really restful

if approve && decline description = agent.page.search("pre").text

if description =~ /Flash/ agent.post decline.href, ""

elsif description =~ /sex/ agent.post decline.href, ""

else agent.post approve.href, ""

end

end

Wednesday, June 9, 2010

Page 128: Making Rails Really restful

No Mechanization?

Wednesday, June 9, 2010

Page 129: Making Rails Really restful

No Mechanization?

Hyperlinks

Wednesday, June 9, 2010

Page 130: Making Rails Really restful

No Mechanization?

HyperlinksNo Semantics

Wednesday, June 9, 2010

Page 131: Making Rails Really restful

No Mechanization?

HyperlinksNo Semantics

Human Heuristics

Wednesday, June 9, 2010

Page 132: Making Rails Really restful

require 'rubygems'require 'active_resource'

class App < ActiveResource::Base self.site = "http://localhost:3000/"end

apps = App.find(:all, :params => { :state => "new" })

Wednesday, June 9, 2010

Page 133: Making Rails Really restful

require 'rubygems'require 'active_resource'

class App < ActiveResource::Base self.site = "http://localhost:3000/"end

apps = App.find(:all, :params => { :state => "new" })

GET /apps?state=new

Wednesday, June 9, 2010

Page 134: Making Rails Really restful

require 'rubygems'require 'active_resource'

class App < ActiveResource::Base self.site = "http://localhost:3000/"end

apps = App.find(:all, :params => { :state => "new" })

GET /apps?state=new

Wednesday, June 9, 2010

Page 135: Making Rails Really restful

require 'rubygems'require 'active_resource'

class App < ActiveResource::Base self.site = "http://localhost:3000/"end

apps = App.find(:all, :params => { :state => "new" })

GET /apps?state=new

Wednesday, June 9, 2010

Page 136: Making Rails Really restful

require 'rubygems'require 'active_resource'

class App < ActiveResource::Base self.site = "http://localhost:3000/"end

apps = App.find(:all, :params => { :state => "new" })

GET /apps?state=new

Wednesday, June 9, 2010

Page 137: Making Rails Really restful

ActionController::Routing::Routes.draw do |map| map.resources :apps, :member => { :evaluate => :post, :approve => :post, :decline => :post }end

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

Wednesday, June 9, 2010

Page 138: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 139: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 140: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 141: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 142: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 143: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 144: Making Rails Really restful

POST /apps/1/evaluatePOST /apps/1/declinePOST /apps/1/approve

app = apps.firstapp.post(:evaluate) if app.state == "new"

if apps.first.description =~ /Flash/ app.post(:decline)

elsif apps.first.description =~ /sex/ app.post(:decline)

else app.post(:approve)end

Wednesday, June 9, 2010

Page 145: Making Rails Really restful

application/xml

<?xml version="1.0" encoding="UTF-8"?><app> <id type="integer">1</id> <title>Facebook</title> <updated_at type="datetime">2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go.</description> <price type="float">0.0</price></app>

Wednesday, June 9, 2010

Page 146: Making Rails Really restful

Why not ActiveResource?

Wednesday, June 9, 2010

Page 147: Making Rails Really restful

Why not ActiveResource?

No Hyperlinks

Wednesday, June 9, 2010

Page 148: Making Rails Really restful

Why not ActiveResource?

No HyperlinksNo Semantics

Wednesday, June 9, 2010

Page 149: Making Rails Really restful

Why not ActiveResource?

No HyperlinksNo Semantics

Doesn’t respect HTTP (etag, last modi"ed)

Wednesday, June 9, 2010

Page 150: Making Rails Really restful

Why not ActiveResource?

No HyperlinksNo Semantics

Doesn’t respect HTTP (etag, last modi"ed)Ruby on Rails only Conventions

Wednesday, June 9, 2010

Page 151: Making Rails Really restful

Why not other web clients?HTTParty, RestClient, Typhoeus, Curb

Wednesday, June 9, 2010

Page 152: Making Rails Really restful

Why not other web clients?

Most are not really “REST”

HTTParty, RestClient, Typhoeus, Curb

Wednesday, June 9, 2010

Page 153: Making Rails Really restful

Why not other web clients?

Most are not really “REST”Just URI consumers

HTTParty, RestClient, Typhoeus, Curb

Wednesday, June 9, 2010

Page 154: Making Rails Really restful

Why not other web clients?

Most are not really “REST”Just URI consumers

Wrappers for low level HTTP connections

HTTParty, RestClient, Typhoeus, Curb

Wednesday, June 9, 2010

Page 155: Making Rails Really restful

One goal is to avoid tight coupling

Wednesday, June 9, 2010

Page 156: Making Rails Really restful

http://restfulie.caelumobjects.com/

Wednesday, June 9, 2010

Page 157: Making Rails Really restful

Restfulie

Wednesday, June 9, 2010

Page 158: Making Rails Really restful

Restfulie

Client and Server solution

Wednesday, June 9, 2010

Page 159: Making Rails Really restful

Restfulie

Client and Server solutionXML, JSON, Atom Representations

Wednesday, June 9, 2010

Page 160: Making Rails Really restful

Restfulie

Client and Server solutionXML, JSON, Atom Representations

Enhances Ruby on Rails

Wednesday, June 9, 2010

Page 161: Making Rails Really restful

Restfulie

Client and Server solutionXML, JSON, Atom Representations

Enhances Ruby on RailsREST Client

Wednesday, June 9, 2010

Page 162: Making Rails Really restful

Restfulie

@guilhermesilveira

@caueguerra

@georgeguimaraes

@lfcipriani

Wednesday, June 9, 2010

Page 163: Making Rails Really restful

app/controllers/apps_controller.rb

class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ...end

Wednesday, June 9, 2010

Page 164: Making Rails Really restful

app/controllers/apps_controller.rb

class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ...end

Wednesday, June 9, 2010

Page 165: Making Rails Really restful

app/controllers/apps_controller.rb

class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ...end

Wednesday, June 9, 2010

Page 166: Making Rails Really restful

app/controllers/apps_controller.rb

class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ...end

Wednesday, June 9, 2010

Page 167: Making Rails Really restful

app/controllers/apps_controller.rb

class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ...end

Wednesday, June 9, 2010

Page 168: Making Rails Really restful

Tokamak

Wednesday, June 9, 2010

Page 169: Making Rails Really restful

Tokamak

Wednesday, June 9, 2010

Page 170: Making Rails Really restful

app/views/apps/index.tokamak

collection(@apps) do |collection| collection.values do |values| values.id apps_url values.title "Apps List" values.updated_at Time.now.utc end collection.members do |member, app| partial "member", :locals => { :member => member, :app => app } endend

Wednesday, June 9, 2010

Page 171: Making Rails Really restful

app/views/apps/index.tokamak

collection(@apps) do |collection| collection.values do |values| values.id apps_url values.title "Apps List" values.updated_at Time.now.utc end collection.members do |member, app| partial "member", :locals => { :member => member, :app => app } endend

Wednesday, June 9, 2010

Page 172: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 173: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 174: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 175: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 176: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 177: Making Rails Really restful

app/views/apps/_member.tokamak

member.values do |value| value.id app.id value.title app.name value.updated_at app.updated_at.utc value.state app.state value.description app.description value.price app.priceendmember.link "show", app_url(app) if app.state == "new" member.link "evaluate", evaluate_app_url(app)elsif app.state == "evaluating" member.link "approve", approve_app_url(app) member.link "decline", decline_app_url(app)end

Wednesday, June 9, 2010

Page 178: Making Rails Really restful

curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1

<entry xmlns="http://www.w3.org/2005/Atom"> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/atom+xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/atom+xml"/></entry>

Wednesday, June 9, 2010

Page 179: Making Rails Really restful

curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1

<entry xmlns="http://www.w3.org/2005/Atom"> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/atom+xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/atom+xml"/></entry>

Wednesday, June 9, 2010

Page 180: Making Rails Really restful

curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1

<entry xmlns="http://www.w3.org/2005/Atom"> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/atom+xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/atom+xml"/></entry>

Wednesday, June 9, 2010

Page 181: Making Rails Really restful

<?xml version="1.0"?><app> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/xml"/></app>

curl -H “Accept: application/xml” http://localhost:3000/apps/1

Wednesday, June 9, 2010

Page 182: Making Rails Really restful

<?xml version="1.0"?><app> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/xml"/></app>

curl -H “Accept: application/xml” http://localhost:3000/apps/1

Wednesday, June 9, 2010

Page 183: Making Rails Really restful

<?xml version="1.0"?><app> <id>1</id> <title>Facebook</title> <updated_at>2010-06-02T14:16:45Z</updated_at> <state>new</state> <description>Facebook for iPhone ... on the go. </description> <price>0.0</price> <link href="http://localhost:3000/apps/1" rel="show" type="application/xml"/> <link href="http://localhost:3000/apps/1/evaluate" rel="evaluate" type="application/xml"/></app>

curl -H “Accept: application/xml” http://localhost:3000/apps/1

Wednesday, June 9, 2010

Page 184: Making Rails Really restful

Mechanizable Web

Wednesday, June 9, 2010

Page 185: Making Rails Really restful

Mechanizable Web

Hyperlinks

Wednesday, June 9, 2010

Page 186: Making Rails Really restful

Mechanizable Web

HyperlinksLink Relations

Wednesday, June 9, 2010

Page 187: Making Rails Really restful

Mechanizable Web

HyperlinksLink Relations

Media Types

Wednesday, June 9, 2010

Page 188: Making Rails Really restful

Mechanizable Web

HyperlinksLink Relations

Media TypesDomain Application Protocol (DAP)

Wednesday, June 9, 2010

Page 189: Making Rails Really restful

Mechanizable Web

HyperlinksLink Relations

Media TypesDomain Application Protocol (DAP)

HATEOAS

Wednesday, June 9, 2010

Page 190: Making Rails Really restful

Mechanizable Web

HyperlinksLink Relations

Media TypesDomain Application Protocol (DAP)

HATEOASHypermedia As The Engine of Application State

Wednesday, June 9, 2010

Page 191: Making Rails Really restful

Protocols

Contract

Wednesday, June 9, 2010

Page 192: Making Rails Really restful

Protocols

Contract

HTTP idioms

Entry-point URIs

Media Types

Protocol

Wednesday, June 9, 2010

Page 193: Making Rails Really restful

Formats Link Relations

Processing Models

Media Type

Schema

Protocols

Contract

HTTP idioms

Entry-point URIs

Media Types

Protocol

Wednesday, June 9, 2010

Page 194: Making Rails Really restful

Improving Restfulie

Wednesday, June 9, 2010

Page 195: Making Rails Really restful

Improving Restfulie

Single interface for representations

Wednesday, June 9, 2010

Page 196: Making Rails Really restful

Improving Restfulie

Single interface for representationsSmart defaults for serialization

Wednesday, June 9, 2010

Page 197: Making Rails Really restful

Improving Restfulie

Single interface for representationsSmart defaults for serialization

XML serialization compatible with Rails

Wednesday, June 9, 2010

Page 198: Making Rails Really restful

Improving Restfulie

Single interface for representationsSmart defaults for serialization

XML serialization compatible with RailsRails 3 compatibility

Wednesday, June 9, 2010

Page 199: Making Rails Really restful

Wednesday, June 9, 2010

Page 200: Making Rails Really restful

One more thing

Wednesday, June 9, 2010

Page 201: Making Rails Really restful

Mikyung

Wednesday, June 9, 2010

Page 202: Making Rails Really restful

Evaluation WorkflowWhen there is a new app

Then move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteria

Then approve the app

When there is an app being evaluated

And the app doesn't pass the criteriaThen decline the app

Wednesday, June 9, 2010

Page 203: Making Rails Really restful

evaluation_process.rb

require 'restfulie'

class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel at "http://localhost:3000/apps/list_new" current_dir File.dirname(__FILE__) follow true

def initialize(*black_list) @black_list = black_list end

def completed?(resource) resource.entries.size == 0 end

def self.run goal = EvaluationProcess.new("Flash", "sex") result = Restfulie::Mikyung.new.achieve(goal).run puts result.response.body endend

Wednesday, June 9, 2010

Page 204: Making Rails Really restful

evaluation_process.rb

require 'restfulie'

class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel at "http://localhost:3000/apps/list_new" current_dir File.dirname(__FILE__) follow true

def initialize(*black_list) @black_list = black_list end

def completed?(resource) resource.entries.size == 0 end

def self.run goal = EvaluationProcess.new("Flash", "sex") result = Restfulie::Mikyung.new.achieve(goal).run puts result.response.body endend

Wednesday, June 9, 2010

Page 205: Making Rails Really restful

evaluation_process.rb

require 'restfulie'

class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel at "http://localhost:3000/apps/list_new" current_dir File.dirname(__FILE__) follow true

def initialize(*black_list) @black_list = black_list end

def completed?(resource) resource.entries.size == 0 end

def self.run goal = EvaluationProcess.new("Flash", "sex") result = Restfulie::Mikyung.new.achieve(goal).run puts result.response.body endend

Wednesday, June 9, 2010

Page 206: Making Rails Really restful

evaluation_process.rb

require 'restfulie'

class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel at "http://localhost:3000/apps/list_new" current_dir File.dirname(__FILE__) follow true

def initialize(*black_list) @black_list = black_list end

def completed?(resource) resource.entries.size == 0 end

def self.run goal = EvaluationProcess.new("Flash", "sex") result = Restfulie::Mikyung.new.achieve(goal).run puts result.response.body endend

Wednesday, June 9, 2010

Page 207: Making Rails Really restful

steps/evaluation_process.rb

def is_valid?(app) result = true @black_list.each do |word| if app.description =~ /#{word}/ result = false end end resultend

Then "move forward to evaluate it" do |resource| @app = @app.links.evaluate.follow.post!("") resourceend

When "the app passes the criteria" do |resource| is_valid?(@app)end

Wednesday, June 9, 2010

Page 208: Making Rails Really restful

steps/evaluation_process.rb

def is_valid?(app) result = true @black_list.each do |word| if app.description =~ /#{word}/ result = false end end resultend

Then "move forward to evaluate it" do |resource| @app = @app.links.evaluate.follow.post!("") resourceend

When "the app passes the criteria" do |resource| is_valid?(@app)end

Wednesday, June 9, 2010

Page 209: Making Rails Really restful

scenarios/evaluation_process.scenario

When there is a new appThen move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteriaThen approve the app

When there is an app being evaluatedAnd the app doesnt pass the criteriaThen decline the app

Wednesday, June 9, 2010

Page 210: Making Rails Really restful

scenarios/evaluation_process.scenario

When there is a new appThen move forward to evaluate it

When there is an app being evaluatedAnd the app passes the criteriaThen approve the app

When there is an app being evaluatedAnd the app doesnt pass the criteriaThen decline the app

This is Ruby Code!

Wednesday, June 9, 2010

Page 211: Making Rails Really restful

EvaluationProcess.run

http://bit.ly/railsconf2010-restfulie

Wednesday, June 9, 2010

Page 212: Making Rails Really restful

Adaptable Client

Wednesday, June 9, 2010

Page 213: Making Rails Really restful

Adaptable Client

Goal Oriented

Wednesday, June 9, 2010

Page 214: Making Rails Really restful

Adaptable Client

Goal OrientedPattern Matching

Wednesday, June 9, 2010

Page 215: Making Rails Really restful

Adaptable Client

Goal OrientedPattern Matching

Can adapt to some changes

Wednesday, June 9, 2010

Page 216: Making Rails Really restful

Richardson Restful ModelRichardson Restful Model

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 217: Making Rails Really restful

Caelum Restful ModelCaelum Restful Model

Level 5 Code on Demand

Level 4 Adaptable Clients

Level 3 Hypermedia

Level 2 HTTP

Level 1 URI

Wednesday, June 9, 2010

Page 218: Making Rails Really restful

We’re not done yet!

Wednesday, June 9, 2010

Page 219: Making Rails Really restful

Wednesday, June 9, 2010

Page 220: Making Rails Really restful

Thank you!@AkitaOnRails

http://bit.ly/railsconf2010-restfulie

Wednesday, June 9, 2010