Making Rails really
           Restful
           Improving the world of Resources on Rails with Restfulie




           ...
The greatest thing
                  about talking to you



Wednesday, June 9, 2010
We’ve been through this
       already!




Wednesday, June 9, 2010
We’ve been through this
       already!


       No WSDL and WS-*




Wednesday, June 9, 2010
We’ve been through this
       already!


       No WSDL and WS-*
       No XML-RPC




Wednesday, June 9, 2010
We’ve been through this
       already!


       No WSDL and WS-*
       No XML-RPC
       No $$ enterprisey stuff



Wedne...
We’ve been through this
       already!


       No WSDL and WS-*
       No XML-RPC
       No $$ enterprisey stuff
        ...
HTTP




Wednesday, June 9, 2010
HTTP



       Shared Nothing Architecture




Wednesday, June 9, 2010
HTTP



       Shared Nothing Architecture
       Stateless




Wednesday, June 9, 2010
HTTP



       Shared Nothing Architecture
       Stateless
       Caching



Wednesday, June 9, 2010
HTTP



       Shared Nothing Architecture
       Stateless
       Caching
       Proxies and Reverse Proxies


Wednesday,...
HTTP



       Shared Nothing Architecture
       Stateless
       Caching
       Proxies and Reverse Proxies


Wednesday,...
Discovering a world of

 Resources on Rails
 David Heinemeir Hansson   RailsConf 2006




Wednesday, June 9, 2010
Create Read Update Delete



Wednesday, June 9, 2010
Wednesday, June 9, 2010
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSE...
POST       /people/create
               GET        /people/show/1
               POST       /people/update/1
            ...
POST       /people
               GET        /people/1
               PUT        /people/1
               DELETE     /peop...
MyApp::Application.routes.draw do |map|
                            resources :people
                          end




We...
class PeopleController < ApplicationController
                     # POST /people/1
                     # POST /people/1...
class PeopleController < ApplicationController
                     # POST /people/1
                     # POST /people/1...
class PeopleController < ApplicationController
                     # POST /people/1
                     # POST /people/1...
class PeopleController < ApplicationController
                     # POST /people/1
                     # POST /people/1...
Answering to mime types




Wednesday, June 9, 2010
Answering to mime types




       One controller for many clients




Wednesday, June 9, 2010
Answering to mime types




       One controller for many clients
       One action returning different representations


...
Answering to mime types




       One controller for many clients
       One action returning different representations
  ...
class PeopleController < ApplicationController
                     def index
                       @people = Person.all
...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def ...
2008
                          Rails 2.2


Wednesday, June 9, 2010
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
class PeopleController < ApplicationController
            respond_to :html, :js, :xml
            def show
              ...
But!



Wednesday, June 9, 2010
CRUD is not a goal,
                      it’s an aspiration,
                     a design technique


Wednesday, June 9,...
And we are not done yet!



Wednesday, June 9, 2010
Why not?




       Consistency
       Simplicity
       Discoverability

Wednesday, June 9, 2010
Why not?




       Consistency
       Simplicity
       Discoverability

Wednesday, June 9, 2010
Why not?




       Consistency
       Simplicity
       Discoverability

Wednesday, June 9, 2010
This is NOT necessarily REST




Wednesday, June 9, 2010
This is NOT necessarily REST




       Using HTTP




Wednesday, June 9, 2010
This is NOT necessarily REST




       Using HTTP
       Using HTTP Verbs (PUT, DELETE)



Wednesday, June 9, 2010
This is NOT necessarily REST




       Using HTTP
       Using HTTP Verbs (PUT, DELETE)
       Pretty URIs

Wednesday, Ju...
Most of what we call
                   “REST” is not REST



Wednesday, June 9, 2010
REST Principles




Wednesday, June 9, 2010
REST Principles



       Identi cation of Resources




Wednesday, June 9, 2010
REST Principles



       Identi cation of Resources
       Manipulate resources through representations




Wednesday, Ju...
REST Principles



       Identi cation of Resources
       Manipulate resources through representations
       Self-descr...
REST Principles



       Identi cation of Resources
       Manipulate resources through representations
       Self-descr...
REST Goals




Wednesday, June 9, 2010
REST Goals



       Scalability of component interactions




Wednesday, June 9, 2010
REST Goals



       Scalability of component interactions
       Generality of interfaces




Wednesday, June 9, 2010
REST Goals



       Scalability of component interactions
       Generality of interfaces
       Independent deployment o...
REST Goals



       Scalability of component interactions
       Generality of interfaces
       Independent deployment o...
REST Goals



       Scalability of component interactions
       Generality of interfaces
       Independent deployment o...
Constraints are liberating
                      (a straight jacket for your mind)




Wednesday, June 9, 2010
Wednesday, June 9, 2010
What are we doing right?




Wednesday, June 9, 2010
What are we doing right?



       Uniform Interface (URI Templates)




Wednesday, June 9, 2010
What are we doing right?



       Uniform Interface (URI Templates)
       HTTP Verbs (some)




Wednesday, June 9, 2010
What are we doing right?



       Uniform Interface (URI Templates)
       HTTP Verbs (some)
       HTTP Status Codes (so...
What are we doing right?



       Uniform Interface (URI Templates)
       HTTP Verbs (some)
       HTTP Status Codes (so...
What is missing?




Wednesday, June 9, 2010
What is missing?




       More HTTP (verbs, status codes, headers)




Wednesday, June 9, 2010
What is missing?




       More HTTP (verbs, status codes, headers)
       Hyperlinks



Wednesday, June 9, 2010
What is missing?




       More HTTP (verbs, status codes, headers)
       Hyperlinks
       Semantic (media-types)

Wedn...
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET        POST      POST    DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET        POST     PATCH    DELETE


                  nd      create   update   destroy


           SELECT         INSE...
GET                  POST                   PUT               PATCH                DELETE


               nd             ...
Why bother?




Wednesday, June 9, 2010
Why bother?




       Consistency




Wednesday, June 9, 2010
Why bother?




       Consistency
       Simplicity



Wednesday, June 9, 2010
Why bother?




       Consistency
       Simplicity
       Discoverability

Wednesday, June 9, 2010
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2      ...
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2      ...
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2      ...
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2      ...
The Web as it is



Wednesday, June 9, 2010
The Web as it is




Wednesday, June 9, 2010
Evaluation Workflow




Wednesday, June 9, 2010
Evaluation Workflow
       When there is a new app




Wednesday, June 9, 2010
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it




Wednesday, June 9, 2010
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
Wednesday, June 9, 2010
The Automated Web?



Wednesday, June 9, 2010
The Automated Web?
                             ?




Wednesday, June 9, 2010
require 'rubygems'
                 require 'mechanize'

                 agent = Mechanize.new { |agent|
                ...
require 'rubygems'
                 require 'mechanize'

                 agent = Mechanize.new { |agent|
                ...
require 'rubygems'
                 require 'mechanize'

                 agent = Mechanize.new { |agent|
                ...
agent.click agent.page.link_with(:href => /apps/d+/)



           evaluate = agent.page.link_with(:text => /Evaluate/)
  ...
agent.click agent.page.link_with(:href => /apps/d+/)



           evaluate = agent.page.link_with(:text => /Evaluate/)
  ...
agent.click agent.page.link_with(:href => /apps/d+/)



           evaluate = agent.page.link_with(:text => /Evaluate/)
  ...
agent.click agent.page.link_with(:href => /apps/d+/)



           evaluate = agent.page.link_with(:text => /Evaluate/)
  ...
if approve && decline
                      description = agent.page.search("pre").text

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

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

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

                          if desc...
No Mechanization?




Wednesday, June 9, 2010
No Mechanization?




       Hyperlinks




Wednesday, June 9, 2010
No Mechanization?




       Hyperlinks
       No Semantics



Wednesday, June 9, 2010
No Mechanization?




       Hyperlinks
       No Semantics
       Human Heuristics

Wednesday, June 9, 2010
require 'rubygems'
            require 'active_resource'

            class App < ActiveResource::Base
              self....
require 'rubygems'
            require 'active_resource'

            class App < ActiveResource::Base
              self....
require 'rubygems'
            require 'active_resource'

            class App < ActiveResource::Base
              self....
require 'rubygems'
            require 'active_resource'

            class App < ActiveResource::Base
              self....
require 'rubygems'
            require 'active_resource'

            class App < ActiveResource::Base
              self....
ActionController::Routing::Routes.draw do |map|
                   map.resources :apps,
                          :member ...
app = apps.first
                          app.post(:evaluate) if app.state == "new"

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

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

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

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

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

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

                          if apps.fi...
<?xml version="1.0" encoding="UTF-8"?>
   <app>
       <id type="integer">1</id>
       <title>Facebook</title>
       <up...
Why not ActiveResource?




Wednesday, June 9, 2010
Why not ActiveResource?



       No Hyperlinks




Wednesday, June 9, 2010
Why not ActiveResource?



       No Hyperlinks
       No Semantics




Wednesday, June 9, 2010
Why not ActiveResource?



       No Hyperlinks
       No Semantics
       Doesn’t respect HTTP (etag, last modi ed)



We...
Why not ActiveResource?



       No Hyperlinks
       No Semantics
       Doesn’t respect HTTP (etag, last modi ed)
     ...
Why not other web clients?
                HTTParty, RestClient, Typhoeus, Curb




Wednesday, June 9, 2010
Why not other web clients?
                HTTParty, RestClient, Typhoeus, Curb




       Most are not really “REST”




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




       Most are not really “REST”
    ...
Why not other web clients?
                HTTParty, RestClient, Typhoeus, Curb




       Most are not really “REST”
    ...
One goal is to avoid
                     tight coupling



Wednesday, June 9, 2010
http://restfulie.caelumobjects.com/

Wednesday, June 9, 2010
Restfulie




Wednesday, June 9, 2010
Restfulie



       Client and Server solution




Wednesday, June 9, 2010
Restfulie



       Client and Server solution
       XML, JSON, Atom Representations




Wednesday, June 9, 2010
Restfulie



       Client and Server solution
       XML, JSON, Atom Representations
       Enhances Ruby on Rails



Wed...
Restfulie



       Client and Server solution
       XML, JSON, Atom Representations
       Enhances Ruby on Rails
      ...
Restfulie

                          @guilhermesilveira



                          @caueguerra



                      ...
class AppsController < ApplicationController
                          restfulie
                          respond_to :htm...
class AppsController < ApplicationController
                          restfulie
                          respond_to :htm...
class AppsController < ApplicationController
                          restfulie
                          respond_to :htm...
class AppsController < ApplicationController
                          restfulie
                          respond_to :htm...
class AppsController < ApplicationController
                          restfulie
                          respond_to :htm...
Tokamak



Wednesday, June 9, 2010
Tokamak




Wednesday, June 9, 2010
collection(@apps) do |collection|
                            collection.values do |values|
                              ...
collection(@apps) do |collection|
                            collection.values do |values|
                              ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
member.values do |value|
                      value.id app.id
                      value.title app.name
                ...
<entry xmlns="http://www.w3.org/2005/Atom">
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02...
<entry xmlns="http://www.w3.org/2005/Atom">
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02...
<entry xmlns="http://www.w3.org/2005/Atom">
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02...
<?xml version="1.0"?>
   <app>
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02T14:16:45Z</u...
<?xml version="1.0"?>
   <app>
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02T14:16:45Z</u...
<?xml version="1.0"?>
   <app>
       <id>1</id>
       <title>Facebook</title>
       <updated_at>2010-06-02T14:16:45Z</u...
Mechanizable Web




Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks




Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks
       Link Relations




Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types




Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types
       Domain Application Protocol (DAP)




...
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types
       Domain Application Protocol (DAP)
    ...
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types
       Domain Application Protocol (DAP)
    ...
Contract
           Protocols




Wednesday, June 9, 2010
Protocol
                          HTTP idioms        Media Types


                          Entry-point URIs



        ...
Media Type
                                  Formats                    Link Relations


                                 ...
Improving Restfulie




Wednesday, June 9, 2010
Improving Restfulie



       Single interface for representations




Wednesday, June 9, 2010
Improving Restfulie



       Single interface for representations
       Smart defaults for serialization




Wednesday, ...
Improving Restfulie



       Single interface for representations
       Smart defaults for serialization
       XML seri...
Improving Restfulie



       Single interface for representations
       Smart defaults for serialization
       XML seri...
Wednesday, June 9, 2010
One more thing



Wednesday, June 9, 2010
Mikyung



Wednesday, June 9, 2010
Evaluation Workflow
       When there is a new app
       Then move forward to evaluate it


       When there is an app b...
require 'restfulie'

     class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel
       at "http://localho...
require 'restfulie'

     class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel
       at "http://localho...
require 'restfulie'

     class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel
       at "http://localho...
require 'restfulie'

     class EvaluationProcess < Restfulie::Client::Mikyung::RestProcessModel
       at "http://localho...
def is_valid?(app)
                            result = true
                            @black_list.each do |word|
      ...
def is_valid?(app)
                            result = true
                            @black_list.each do |word|
      ...
When there is a new app
                          Then move forward to evaluate it

                          When there i...
When there is a new app
                          Then move forward to evaluate it

                          When there i...
EvaluationProcess.run




                          http://bit.ly/railsconf2010-restfulie
Wednesday, June 9, 2010
Adaptable Client




Wednesday, June 9, 2010
Adaptable Client




       Goal Oriented




Wednesday, June 9, 2010
Adaptable Client




       Goal Oriented
       Pattern Matching



Wednesday, June 9, 2010
Adaptable Client




       Goal Oriented
       Pattern Matching
       Can adapt to some changes

Wednesday, June 9, 2010
Richardson Restful Model


                          Level 3            Hypermedia


                          Level 2    ...
Caelum Restful Model

                          Level 5         Code on Demand

                          Level 4         ...
We’re not done yet!



Wednesday, June 9, 2010
Wednesday, June 9, 2010
Thank you!
                                           @AkitaOnRails




                          http://bit.ly/railsconf2...
Upcoming SlideShare
Loading in...5
×

Making Rails Really restful

9,213

Published on

Published in: Technology, Education
1 Comment
31 Likes
Statistics
Notes
No Downloads
Views
Total Views
9,213
On Slideshare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
210
Comments
1
Likes
31
Embeds 0
No embeds

No notes for slide

Making Rails Really restful

  1. 1. Making Rails really Restful Improving the world of Resources on Rails with Restfulie Fabio Akita - akitaonrails.com - @akitaonrails Wednesday, June 9, 2010
  2. 2. The greatest thing about talking to you Wednesday, June 9, 2010
  3. 3. We’ve been through this already! Wednesday, June 9, 2010
  4. 4. We’ve been through this already! No WSDL and WS-* Wednesday, June 9, 2010
  5. 5. We’ve been through this already! No WSDL and WS-* No XML-RPC Wednesday, June 9, 2010
  6. 6. We’ve been through this already! No WSDL and WS-* No XML-RPC No $$ enterprisey stuff Wednesday, June 9, 2010
  7. 7. We’ve been through this already! No WSDL and WS-* No XML-RPC No $$ enterprisey stuff HTTP Wednesday, June 9, 2010
  8. 8. HTTP Wednesday, June 9, 2010
  9. 9. HTTP Shared Nothing Architecture Wednesday, June 9, 2010
  10. 10. HTTP Shared Nothing Architecture Stateless Wednesday, June 9, 2010
  11. 11. HTTP Shared Nothing Architecture Stateless Caching Wednesday, June 9, 2010
  12. 12. HTTP Shared Nothing Architecture Stateless Caching Proxies and Reverse Proxies Wednesday, June 9, 2010
  13. 13. HTTP Shared Nothing Architecture Stateless Caching Proxies and Reverse Proxies Wednesday, June 9, 2010
  14. 14. Discovering a world of Resources on Rails David Heinemeir Hansson RailsConf 2006 Wednesday, June 9, 2010
  15. 15. Create Read Update Delete Wednesday, June 9, 2010
  16. 16. Wednesday, June 9, 2010
  17. 17. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  18. 18. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  19. 19. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  20. 20. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  21. 21. POST /people/create GET /people/show/1 POST /people/update/1 POST /people/destroy/1 Wednesday, June 9, 2010
  22. 22. POST /people GET /people/1 PUT /people/1 DELETE /people/1 Wednesday, June 9, 2010
  23. 23. MyApp::Application.routes.draw do |map| resources :people end Wednesday, June 9, 2010
  24. 24. class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create form_for(@person) do |f| end f.text_field :name 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 end end Wednesday, June 9, 2010
  25. 25. class PeopleController < ApplicationController # POST /people/1 # POST /people/1.xml def create end # GET /people # GET /people.xml def show link_to 'Show', person end # PUT /people/1 # PUT /people/1.xml def update end # DELETE /people/1 # DELETE /people/1.xml def destroy end end Wednesday, June 9, 2010
  26. 26. 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 form_for(@person) do |f| end f.text_field :name end # DELETE /people/1 # DELETE /people/1.xml def destroy end end Wednesday, June 9, 2010
  27. 27. 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 link_to 'Destroy', end person, :method => :delete end Wednesday, June 9, 2010
  28. 28. Answering to mime types Wednesday, June 9, 2010
  29. 29. Answering to mime types One controller for many clients Wednesday, June 9, 2010
  30. 30. Answering to mime types One controller for many clients One action returning different representations Wednesday, June 9, 2010
  31. 31. Answering to mime types One controller for many clients One action returning different representations “Content Negotiation" Wednesday, June 9, 2010
  32. 32. 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 end end Wednesday, June 9, 2010
  33. 33. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end Wednesday, June 9, 2010
  34. 34. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end Wednesday, June 9, 2010
  35. 35. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end GET /people GET /people.xml => returns HTML => returns XML Accept: text/javascript Accept: text/xml GET /people GET /people => returns JS => returns XML Wednesday, June 9, 2010
  36. 36. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end GET /people GET /people.xml => returns HTML => returns XML Accept: text/javascript Accept: text/xml GET /people GET /people => returns JS => returns XML Wednesday, June 9, 2010
  37. 37. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end GET /people GET /people.xml => returns HTML => returns XML Accept: text/javascript Accept: text/xml GET /people GET /people => returns JS => returns XML Wednesday, June 9, 2010
  38. 38. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end GET /people GET /people.xml => returns HTML => returns XML Accept: text/javascript Accept: text/xml GET /people GET /people => returns JS => returns XML Wednesday, June 9, 2010
  39. 39. 2008 Rails 2.2 Wednesday, June 9, 2010
  40. 40. 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 end end Wednesday, June 9, 2010
  41. 41. 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 end end Wednesday, June 9, 2010
  42. 42. 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 end end GET /people/1 Wednesday, June 9, 2010
  43. 43. 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 end end GET /people/1 => returns: HTTP/1.1 200 OK Etag: "fd19b85b6ba49b5778de34310d141319" Last-Modified: Fri, 21 May 2010 05:31:11 GMT Content-Type: text/html; charset=utf-8 Cache-Control: public ... Wednesday, June 9, 2010
  44. 44. 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 end end GET /people/1 => returns: HTTP/1.1 200 OK Etag: "fd19b85b6ba49b5778de34310d141319" Last-Modified: Fri, 21 May 2010 05:31:11 GMT Content-Type: text/html; charset=utf-8 Cache-Control: public ... Wednesday, June 9, 2010
  45. 45. 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 end end If-None-Match: "fd19b85b6ba49b5778de34310d141319" GET /people/1 Wednesday, June 9, 2010
  46. 46. 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 end end If-None-Match: "fd19b85b6ba49b5778de34310d141319" GET /people/1 Wednesday, June 9, 2010
  47. 47. 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 end end 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 GMT Cache-Control: public ... Wednesday, June 9, 2010
  48. 48. 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 end end 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 GMT Cache-Control: public ... Wednesday, June 9, 2010
  49. 49. But! Wednesday, June 9, 2010
  50. 50. CRUD is not a goal, it’s an aspiration, a design technique Wednesday, June 9, 2010
  51. 51. And we are not done yet! Wednesday, June 9, 2010
  52. 52. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  53. 53. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  54. 54. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  55. 55. This is NOT necessarily REST Wednesday, June 9, 2010
  56. 56. This is NOT necessarily REST Using HTTP Wednesday, June 9, 2010
  57. 57. This is NOT necessarily REST Using HTTP Using HTTP Verbs (PUT, DELETE) Wednesday, June 9, 2010
  58. 58. This is NOT necessarily REST Using HTTP Using HTTP Verbs (PUT, DELETE) Pretty URIs Wednesday, June 9, 2010
  59. 59. Most of what we call “REST” is not REST Wednesday, June 9, 2010
  60. 60. REST Principles Wednesday, June 9, 2010
  61. 61. REST Principles Identi cation of Resources Wednesday, June 9, 2010
  62. 62. REST Principles Identi cation of Resources Manipulate resources through representations Wednesday, June 9, 2010
  63. 63. REST Principles Identi cation of Resources Manipulate resources through representations Self-descriptive messages Wednesday, June 9, 2010
  64. 64. REST Principles Identi cation of Resources Manipulate resources through representations Self-descriptive messages HATEOAS Wednesday, June 9, 2010
  65. 65. REST Goals Wednesday, June 9, 2010
  66. 66. REST Goals Scalability of component interactions Wednesday, June 9, 2010
  67. 67. REST Goals Scalability of component interactions Generality of interfaces Wednesday, June 9, 2010
  68. 68. REST Goals Scalability of component interactions Generality of interfaces Independent deployment of components Wednesday, June 9, 2010
  69. 69. REST Goals Scalability of component interactions Generality of interfaces Independent deployment of components Reduce latency, enforce security Wednesday, June 9, 2010
  70. 70. REST Goals Scalability of component interactions Generality of interfaces Independent deployment of components Reduce latency, enforce security http://en.wikipedia.org/wiki/Representational_State_Transfer#Guiding_principles_of_a_REST_interface Wednesday, June 9, 2010
  71. 71. Constraints are liberating (a straight jacket for your mind) Wednesday, June 9, 2010
  72. 72. Wednesday, June 9, 2010
  73. 73. What are we doing right? Wednesday, June 9, 2010
  74. 74. What are we doing right? Uniform Interface (URI Templates) Wednesday, June 9, 2010
  75. 75. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) Wednesday, June 9, 2010
  76. 76. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) HTTP Status Codes (some) Wednesday, June 9, 2010
  77. 77. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) HTTP Status Codes (some) Content Negotiation Wednesday, June 9, 2010
  78. 78. What is missing? Wednesday, June 9, 2010
  79. 79. What is missing? More HTTP (verbs, status codes, headers) Wednesday, June 9, 2010
  80. 80. What is missing? More HTTP (verbs, status codes, headers) Hyperlinks Wednesday, June 9, 2010
  81. 81. What is missing? More HTTP (verbs, status codes, headers) Hyperlinks Semantic (media-types) Wednesday, June 9, 2010
  82. 82. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  83. 83. GET POST POST DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  84. 84. GET POST PATCH DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  85. 85. 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
  86. 86. Why bother? Wednesday, June 9, 2010
  87. 87. Why bother? Consistency Wednesday, June 9, 2010
  88. 88. Why bother? Consistency Simplicity Wednesday, June 9, 2010
  89. 89. Why bother? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  90. 90. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  91. 91. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  92. 92. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  93. 93. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  94. 94. The Web as it is Wednesday, June 9, 2010
  95. 95. The Web as it is Wednesday, June 9, 2010
  96. 96. Evaluation Workflow Wednesday, June 9, 2010
  97. 97. Evaluation Workflow When there is a new app Wednesday, June 9, 2010
  98. 98. Evaluation Workflow When there is a new app Then move forward to evaluate it Wednesday, June 9, 2010
  99. 99. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated Wednesday, June 9, 2010
  100. 100. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Wednesday, June 9, 2010
  101. 101. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app Wednesday, June 9, 2010
  102. 102. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app When there is an app being evaluated Wednesday, June 9, 2010
  103. 103. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And 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
  104. 104. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app When there is an app being evaluated And the app doesn't pass the criteria Then decline the app Wednesday, June 9, 2010
  105. 105. Wednesday, June 9, 2010
  106. 106. Wednesday, June 9, 2010
  107. 107. Wednesday, June 9, 2010
  108. 108. Wednesday, June 9, 2010
  109. 109. Wednesday, June 9, 2010
  110. 110. Wednesday, June 9, 2010
  111. 111. Wednesday, June 9, 2010
  112. 112. Wednesday, June 9, 2010
  113. 113. Wednesday, June 9, 2010
  114. 114. Wednesday, June 9, 2010
  115. 115. The Automated Web? Wednesday, June 9, 2010
  116. 116. The Automated Web? ? Wednesday, June 9, 2010
  117. 117. 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
  118. 118. 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
  119. 119. 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
  120. 120. 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
  121. 121. 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
  122. 122. 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
  123. 123. 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
  124. 124. 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
  125. 125. 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
  126. 126. 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
  127. 127. 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
  128. 128. No Mechanization? Wednesday, June 9, 2010
  129. 129. No Mechanization? Hyperlinks Wednesday, June 9, 2010
  130. 130. No Mechanization? Hyperlinks No Semantics Wednesday, June 9, 2010
  131. 131. No Mechanization? Hyperlinks No Semantics Human Heuristics Wednesday, June 9, 2010
  132. 132. 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
  133. 133. 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
  134. 134. 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
  135. 135. 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
  136. 136. 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
  137. 137. ActionController::Routing::Routes.draw do |map| map.resources :apps, :member => { :evaluate => :post, :approve => :post, :decline => :post } end POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  138. 138. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  139. 139. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  140. 140. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  141. 141. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  142. 142. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  143. 143. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  144. 144. app = apps.first app.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 POST /apps/1/evaluate POST /apps/1/decline POST /apps/1/approve Wednesday, June 9, 2010
  145. 145. <?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> application/xml Wednesday, June 9, 2010
  146. 146. Why not ActiveResource? Wednesday, June 9, 2010
  147. 147. Why not ActiveResource? No Hyperlinks Wednesday, June 9, 2010
  148. 148. Why not ActiveResource? No Hyperlinks No Semantics Wednesday, June 9, 2010
  149. 149. Why not ActiveResource? No Hyperlinks No Semantics Doesn’t respect HTTP (etag, last modi ed) Wednesday, June 9, 2010
  150. 150. Why not ActiveResource? No Hyperlinks No Semantics Doesn’t respect HTTP (etag, last modi ed) Ruby on Rails only Conventions Wednesday, June 9, 2010
  151. 151. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Wednesday, June 9, 2010
  152. 152. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Most are not really “REST” Wednesday, June 9, 2010
  153. 153. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Most are not really “REST” Just URI consumers Wednesday, June 9, 2010
  154. 154. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Most are not really “REST” Just URI consumers Wrappers for low level HTTP connections Wednesday, June 9, 2010
  155. 155. One goal is to avoid tight coupling Wednesday, June 9, 2010
  156. 156. http://restfulie.caelumobjects.com/ Wednesday, June 9, 2010
  157. 157. Restfulie Wednesday, June 9, 2010
  158. 158. Restfulie Client and Server solution Wednesday, June 9, 2010
  159. 159. Restfulie Client and Server solution XML, JSON, Atom Representations Wednesday, June 9, 2010
  160. 160. Restfulie Client and Server solution XML, JSON, Atom Representations Enhances Ruby on Rails Wednesday, June 9, 2010
  161. 161. Restfulie Client and Server solution XML, JSON, Atom Representations Enhances Ruby on Rails REST Client Wednesday, June 9, 2010
  162. 162. Restfulie @guilhermesilveira @caueguerra @georgeguimaraes @lfcipriani Wednesday, June 9, 2010
  163. 163. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  164. 164. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  165. 165. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  166. 166. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  167. 167. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  168. 168. Tokamak Wednesday, June 9, 2010
  169. 169. Tokamak Wednesday, June 9, 2010
  170. 170. 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 } end end app/views/apps/index.tokamak Wednesday, June 9, 2010
  171. 171. 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 } end end app/views/apps/index.tokamak Wednesday, June 9, 2010
  172. 172. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  173. 173. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  174. 174. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  175. 175. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  176. 176. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  177. 177. 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.price end member.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 app/views/apps/_member.tokamak Wednesday, June 9, 2010
  178. 178. <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> curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1 Wednesday, June 9, 2010
  179. 179. <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> curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1 Wednesday, June 9, 2010
  180. 180. <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> curl -H “Accept: application/atom+xml” http://localhost:3000/apps/1 Wednesday, June 9, 2010
  181. 181. <?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
  182. 182. <?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
  183. 183. <?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
  184. 184. Mechanizable Web Wednesday, June 9, 2010
  185. 185. Mechanizable Web Hyperlinks Wednesday, June 9, 2010
  186. 186. Mechanizable Web Hyperlinks Link Relations Wednesday, June 9, 2010
  187. 187. Mechanizable Web Hyperlinks Link Relations Media Types Wednesday, June 9, 2010
  188. 188. Mechanizable Web Hyperlinks Link Relations Media Types Domain Application Protocol (DAP) Wednesday, June 9, 2010
  189. 189. Mechanizable Web Hyperlinks Link Relations Media Types Domain Application Protocol (DAP) HATEOAS Wednesday, June 9, 2010
  190. 190. Mechanizable Web Hyperlinks Link Relations Media Types Domain Application Protocol (DAP) HATEOAS Hypermedia As The Engine of Application State Wednesday, June 9, 2010
  191. 191. Contract Protocols Wednesday, June 9, 2010
  192. 192. Protocol HTTP idioms Media Types Entry-point URIs Contract Protocols Wednesday, June 9, 2010
  193. 193. Media Type Formats Link Relations Processing Models Schema Protocol HTTP idioms Media Types Entry-point URIs Contract Protocols Wednesday, June 9, 2010
  194. 194. Improving Restfulie Wednesday, June 9, 2010
  195. 195. Improving Restfulie Single interface for representations Wednesday, June 9, 2010
  196. 196. Improving Restfulie Single interface for representations Smart defaults for serialization Wednesday, June 9, 2010
  197. 197. Improving Restfulie Single interface for representations Smart defaults for serialization XML serialization compatible with Rails Wednesday, June 9, 2010
  198. 198. Improving Restfulie Single interface for representations Smart defaults for serialization XML serialization compatible with Rails Rails 3 compatibility Wednesday, June 9, 2010
  199. 199. Wednesday, June 9, 2010
  200. 200. One more thing Wednesday, June 9, 2010
  201. 201. Mikyung Wednesday, June 9, 2010
  202. 202. Evaluation Workflow When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app When there is an app being evaluated And the app doesn't pass the criteria Then decline the app Wednesday, June 9, 2010
  203. 203. 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 end end evaluation_process.rb Wednesday, June 9, 2010
  204. 204. 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 end end evaluation_process.rb Wednesday, June 9, 2010
  205. 205. 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 end end evaluation_process.rb Wednesday, June 9, 2010
  206. 206. 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 end end evaluation_process.rb Wednesday, June 9, 2010
  207. 207. def is_valid?(app) result = true @black_list.each do |word| if app.description =~ /#{word}/ result = false end end result end Then "move forward to evaluate it" do |resource| @app = @app.links.evaluate.follow.post!("") resource end When "the app passes the criteria" do |resource| is_valid?(@app) end steps/evaluation_process.rb Wednesday, June 9, 2010
  208. 208. def is_valid?(app) result = true @black_list.each do |word| if app.description =~ /#{word}/ result = false end end result end Then "move forward to evaluate it" do |resource| @app = @app.links.evaluate.follow.post!("") resource end When "the app passes the criteria" do |resource| is_valid?(@app) end steps/evaluation_process.rb Wednesday, June 9, 2010
  209. 209. When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app When there is an app being evaluated And the app doesnt pass the criteria Then decline the app scenarios/evaluation_process.scenario Wednesday, June 9, 2010
  210. 210. When there is a new app Then move forward to evaluate it When there is an app being evaluated And the app passes the criteria Then approve the app When there is an app being evaluated And the app doesnt pass the criteria Then decline the app This is Ruby Code! scenarios/evaluation_process.scenario Wednesday, June 9, 2010
  211. 211. EvaluationProcess.run http://bit.ly/railsconf2010-restfulie Wednesday, June 9, 2010
  212. 212. Adaptable Client Wednesday, June 9, 2010
  213. 213. Adaptable Client Goal Oriented Wednesday, June 9, 2010
  214. 214. Adaptable Client Goal Oriented Pattern Matching Wednesday, June 9, 2010
  215. 215. Adaptable Client Goal Oriented Pattern Matching Can adapt to some changes Wednesday, June 9, 2010
  216. 216. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  217. 217. Caelum Restful Model Level 5 Code on Demand Level 4 Adaptable Clients Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  218. 218. We’re not done yet! Wednesday, June 9, 2010
  219. 219. Wednesday, June 9, 2010
  220. 220. Thank you! @AkitaOnRails http://bit.ly/railsconf2010-restfulie Wednesday, June 9, 2010
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×