SlideShare a Scribd company logo
1 of 220
Download to read offline
Making Rails really
           Restful
           Improving the world of Resources on Rails with Restfulie




            Fabio Akita - akitaonrails.com - @akitaonrails

Wednesday, June 9, 2010
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



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


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

Wednesday, June 9, 2010
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, June 9, 2010
HTTP



       Shared Nothing Architecture
       Stateless
       Caching
       Proxies and Reverse Proxies


Wednesday, June 9, 2010
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         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
POST       /people/create
               GET        /people/show/1
               POST       /people/update/1
               POST       /people/destroy/1




Wednesday, June 9, 2010
POST       /people
               GET        /people/1
               PUT        /people/1
               DELETE     /people/1




Wednesday, June 9, 2010
MyApp::Application.routes.draw do |map|
                            resources :people
                          end




Wednesday, June 9, 2010
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
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
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
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
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



Wednesday, June 9, 2010
Answering to mime types




       One controller for many clients
       One action returning different representations
       “Content Negotiation"

Wednesday, June 9, 2010
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
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def index
                       @people = Person.all
                       respond_with(@people)
                     end
                   end




Wednesday, June 9, 2010
class PeopleController < ApplicationController
                     respond_to :html, :js, :xml

                     def index
                       @people = Person.all
                       respond_with(@people)
                     end
                   end




Wednesday, June 9, 2010
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
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
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
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
2008
                          Rails 2.2


Wednesday, June 9, 2010
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
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
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
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
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
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
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
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
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
But!



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


Wednesday, June 9, 2010
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, June 9, 2010
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, June 9, 2010
REST Principles



       Identi cation of Resources
       Manipulate resources through representations
       Self-descriptive messages



Wednesday, June 9, 2010
REST Principles



       Identi cation of Resources
       Manipulate resources through representations
       Self-descriptive messages
       HATEOAS

Wednesday, June 9, 2010
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 of components



Wednesday, June 9, 2010
REST Goals



       Scalability of component interactions
       Generality of interfaces
       Independent deployment of components
       Reduce latency, enforce security

Wednesday, June 9, 2010
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
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 (some)



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



       Uniform Interface (URI Templates)
       HTTP Verbs (some)
       HTTP Status Codes (some)
       Content Negotiation

Wednesday, June 9, 2010
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)

Wednesday, June 9, 2010
GET        POST      PUT     DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
GET        POST      POST    DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
GET        POST     PATCH    DELETE


                  nd      create   update   destroy


           SELECT         INSERT   UPDATE   DELETE




Wednesday, June 9, 2010
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
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               HTTP

                          Level 1                URI



Wednesday, June 9, 2010
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2               HTTP

                          Level 1                URI



Wednesday, June 9, 2010
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2               HTTP

                          Level 1                URI



Wednesday, June 9, 2010
Richardson Restful Model

                          Level 3            Hypermedia

                          Level 2               HTTP

                          Level 1                URI



Wednesday, June 9, 2010
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 being evaluated




Wednesday, June 9, 2010
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
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
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
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
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
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|
                   agent.user_agent_alias = "Mac Safari"
                 }

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




Wednesday, June 9, 2010
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
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
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
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
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
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
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
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
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
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
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.site = "http://localhost:3000/"
            end

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




Wednesday, June 9, 2010
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
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
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
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
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
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
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
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
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
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
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
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
<?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
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)



Wednesday, June 9, 2010
Why not ActiveResource?



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

Wednesday, June 9, 2010
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”




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




       Most are not really “REST”
       Just URI consumers



Wednesday, June 9, 2010
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
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



Wednesday, June 9, 2010
Restfulie



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

Wednesday, June 9, 2010
Restfulie

                          @guilhermesilveira



                          @caueguerra



                          @georgeguimaraes



                          @lfcipriani

Wednesday, June 9, 2010
class AppsController < ApplicationController
                          restfulie
                          respond_to :html, :xml, :atom
                          inherit_resources


                          ...
                     end




                     app/controllers/apps_controller.rb
Wednesday, June 9, 2010
class AppsController < ApplicationController
                          restfulie
                          respond_to :html, :xml, :atom
                          inherit_resources


                          ...
                     end




                     app/controllers/apps_controller.rb
Wednesday, June 9, 2010
class AppsController < ApplicationController
                          restfulie
                          respond_to :html, :xml, :atom
                          inherit_resources


                          ...
                     end




                     app/controllers/apps_controller.rb
Wednesday, June 9, 2010
class AppsController < ApplicationController
                          restfulie
                          respond_to :html, :xml, :atom
                          inherit_resources


                          ...
                     end




                     app/controllers/apps_controller.rb
Wednesday, June 9, 2010
class AppsController < ApplicationController
                          restfulie
                          respond_to :html, :xml, :atom
                          inherit_resources


                          ...
                     end




                     app/controllers/apps_controller.rb
Wednesday, June 9, 2010
Tokamak



Wednesday, June 9, 2010
Tokamak




Wednesday, June 9, 2010
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
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
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
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
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
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
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
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
<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
<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
<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
<?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
<?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
<?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
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)




Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types
       Domain Application Protocol (DAP)
       HATEOAS


Wednesday, June 9, 2010
Mechanizable Web

       Hyperlinks
       Link Relations
       Media Types
       Domain Application Protocol (DAP)
       HATEOAS
          Hypermedia As The Engine of Application State


Wednesday, June 9, 2010
Contract
           Protocols




Wednesday, June 9, 2010
Protocol
                          HTTP idioms        Media Types


                          Entry-point URIs



          Contract
           Protocols




Wednesday, June 9, 2010
Media Type
                                  Formats                    Link Relations


                                                             Processing Models
                                     Schema




                          Protocol
                          HTTP idioms          Media Types


                          Entry-point URIs



          Contract
           Protocols




Wednesday, June 9, 2010
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, June 9, 2010
Improving Restfulie



       Single interface for representations
       Smart defaults for serialization
       XML serialization compatible with Rails



Wednesday, June 9, 2010
Improving Restfulie



       Single interface for representations
       Smart defaults for serialization
       XML serialization compatible with Rails
       Rails 3 compatibility

Wednesday, June 9, 2010
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 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
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
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
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
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
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
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
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
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
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               HTTP


                          Level 1                URI


Wednesday, June 9, 2010
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
We’re not done yet!



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




                          http://bit.ly/railsconf2010-restfulie



Wednesday, June 9, 2010

More Related Content

More from Fabio Akita

Devconf 2019 - São Carlos
Devconf 2019 - São CarlosDevconf 2019 - São Carlos
Devconf 2019 - São CarlosFabio Akita
 
Meetup Nerdzão - English Talk about Languages
Meetup Nerdzão  - English Talk about LanguagesMeetup Nerdzão  - English Talk about Languages
Meetup Nerdzão - English Talk about LanguagesFabio Akita
 
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018Fabio Akita
 
Desmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SPDesmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SPFabio Akita
 
Desmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter GoianiaDesmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter GoianiaFabio Akita
 
Blockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7MastersBlockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7MastersFabio Akita
 
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG CampinasFabio Akita
 
Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017Fabio Akita
 
30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to Ruby30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to RubyFabio Akita
 
Uma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TIUma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TIFabio Akita
 
THE CONF - Opening Keynote
THE CONF - Opening KeynoteTHE CONF - Opening Keynote
THE CONF - Opening KeynoteFabio Akita
 
A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017Fabio Akita
 
Desmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - APDesmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - APFabio Akita
 
A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017Fabio Akita
 
A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017Fabio Akita
 
A Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech DayA Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech DayFabio Akita
 
A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016Fabio Akita
 
Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016Fabio Akita
 
Conexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização PrematuraConexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização PrematuraFabio Akita
 
The Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All EvilThe Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All EvilFabio Akita
 

More from Fabio Akita (20)

Devconf 2019 - São Carlos
Devconf 2019 - São CarlosDevconf 2019 - São Carlos
Devconf 2019 - São Carlos
 
Meetup Nerdzão - English Talk about Languages
Meetup Nerdzão  - English Talk about LanguagesMeetup Nerdzão  - English Talk about Languages
Meetup Nerdzão - English Talk about Languages
 
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
Desmistificando Blockchains p/ Developers - Criciuma Dev Conf 2018
 
Desmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SPDesmistificando Blockchains - 20o Encontro Locaweb SP
Desmistificando Blockchains - 20o Encontro Locaweb SP
 
Desmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter GoianiaDesmistificando Blockchains - Insiter Goiania
Desmistificando Blockchains - Insiter Goiania
 
Blockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7MastersBlockchain em 7 minutos - 7Masters
Blockchain em 7 minutos - 7Masters
 
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
 
Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017Desmistificando Mitos de Tech Startups - Intercon 2017
Desmistificando Mitos de Tech Startups - Intercon 2017
 
30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to Ruby30 Days to Elixir and Crystal and Back to Ruby
30 Days to Elixir and Crystal and Back to Ruby
 
Uma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TIUma Discussão sobre a Carreira de TI
Uma Discussão sobre a Carreira de TI
 
THE CONF - Opening Keynote
THE CONF - Opening KeynoteTHE CONF - Opening Keynote
THE CONF - Opening Keynote
 
A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017A Journey through New Languages - Rancho Dev 2017
A Journey through New Languages - Rancho Dev 2017
 
Desmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - APDesmistificando Mitos de Startups - Sebrae - AP
Desmistificando Mitos de Startups - Sebrae - AP
 
A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017A Journey through New Languages - Guru Sorocaba 2017
A Journey through New Languages - Guru Sorocaba 2017
 
A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017A Journey through New Languages - Insiter 2017
A Journey through New Languages - Insiter 2017
 
A Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech DayA Journey through New Languages - Locaweb Tech Day
A Journey through New Languages - Locaweb Tech Day
 
A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016A Journey through new Languages - Intercon 2016
A Journey through new Languages - Intercon 2016
 
Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016Premature Optimization 2.0 - Intercon 2016
Premature Optimization 2.0 - Intercon 2016
 
Conexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização PrematuraConexão Kinghost - Otimização Prematura
Conexão Kinghost - Otimização Prematura
 
The Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All EvilThe Open Commerce Conference - Premature Optimisation: The Root of All Evil
The Open Commerce Conference - Premature Optimisation: The Root of All Evil
 

Recently uploaded

Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 

Recently uploaded (20)

Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 

Making Rails Really restful

  • 1. Making Rails really Restful Improving the world of Resources on Rails with Restfulie Fabio Akita - akitaonrails.com - @akitaonrails Wednesday, June 9, 2010
  • 2. The greatest thing about talking to you Wednesday, June 9, 2010
  • 3. We’ve been through this already! Wednesday, June 9, 2010
  • 4. We’ve been through this already! No WSDL and WS-* Wednesday, June 9, 2010
  • 5. We’ve been through this already! No WSDL and WS-* No XML-RPC Wednesday, June 9, 2010
  • 6. We’ve been through this already! No WSDL and WS-* No XML-RPC No $$ enterprisey stuff Wednesday, June 9, 2010
  • 7. We’ve been through this already! No WSDL and WS-* No XML-RPC No $$ enterprisey stuff HTTP Wednesday, June 9, 2010
  • 9. HTTP Shared Nothing Architecture Wednesday, June 9, 2010
  • 10. HTTP Shared Nothing Architecture Stateless Wednesday, June 9, 2010
  • 11. HTTP Shared Nothing Architecture Stateless Caching Wednesday, June 9, 2010
  • 12. HTTP Shared Nothing Architecture Stateless Caching Proxies and Reverse Proxies Wednesday, June 9, 2010
  • 13. HTTP Shared Nothing Architecture Stateless Caching Proxies and Reverse Proxies Wednesday, June 9, 2010
  • 14. Discovering a world of Resources on Rails David Heinemeir Hansson RailsConf 2006 Wednesday, June 9, 2010
  • 15. Create Read Update Delete Wednesday, June 9, 2010
  • 17. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 18. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 19. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 20. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 21. POST /people/create GET /people/show/1 POST /people/update/1 POST /people/destroy/1 Wednesday, June 9, 2010
  • 22. POST /people GET /people/1 PUT /people/1 DELETE /people/1 Wednesday, June 9, 2010
  • 23. MyApp::Application.routes.draw do |map| resources :people end Wednesday, June 9, 2010
  • 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. 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. 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. 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. Answering to mime types Wednesday, June 9, 2010
  • 29. Answering to mime types One controller for many clients Wednesday, June 9, 2010
  • 30. Answering to mime types One controller for many clients One action returning different representations Wednesday, June 9, 2010
  • 31. Answering to mime types One controller for many clients One action returning different representations “Content Negotiation" Wednesday, June 9, 2010
  • 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. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end Wednesday, June 9, 2010
  • 34. class PeopleController < ApplicationController respond_to :html, :js, :xml def index @people = Person.all respond_with(@people) end end Wednesday, June 9, 2010
  • 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. 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. 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. 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. 2008 Rails 2.2 Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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
  • 50. CRUD is not a goal, it’s an aspiration, a design technique Wednesday, June 9, 2010
  • 51. And we are not done yet! Wednesday, June 9, 2010
  • 52. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  • 53. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  • 54. Why not? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  • 55. This is NOT necessarily REST Wednesday, June 9, 2010
  • 56. This is NOT necessarily REST Using HTTP Wednesday, June 9, 2010
  • 57. This is NOT necessarily REST Using HTTP Using HTTP Verbs (PUT, DELETE) Wednesday, June 9, 2010
  • 58. This is NOT necessarily REST Using HTTP Using HTTP Verbs (PUT, DELETE) Pretty URIs Wednesday, June 9, 2010
  • 59. Most of what we call “REST” is not REST Wednesday, June 9, 2010
  • 61. REST Principles Identi cation of Resources Wednesday, June 9, 2010
  • 62. REST Principles Identi cation of Resources Manipulate resources through representations Wednesday, June 9, 2010
  • 63. REST Principles Identi cation of Resources Manipulate resources through representations Self-descriptive messages Wednesday, June 9, 2010
  • 64. REST Principles Identi cation of Resources Manipulate resources through representations Self-descriptive messages HATEOAS Wednesday, June 9, 2010
  • 66. REST Goals Scalability of component interactions Wednesday, June 9, 2010
  • 67. REST Goals Scalability of component interactions Generality of interfaces Wednesday, June 9, 2010
  • 68. REST Goals Scalability of component interactions Generality of interfaces Independent deployment of components Wednesday, June 9, 2010
  • 69. REST Goals Scalability of component interactions Generality of interfaces Independent deployment of components Reduce latency, enforce security Wednesday, June 9, 2010
  • 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. Constraints are liberating (a straight jacket for your mind) Wednesday, June 9, 2010
  • 73. What are we doing right? Wednesday, June 9, 2010
  • 74. What are we doing right? Uniform Interface (URI Templates) Wednesday, June 9, 2010
  • 75. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) Wednesday, June 9, 2010
  • 76. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) HTTP Status Codes (some) Wednesday, June 9, 2010
  • 77. What are we doing right? Uniform Interface (URI Templates) HTTP Verbs (some) HTTP Status Codes (some) Content Negotiation Wednesday, June 9, 2010
  • 79. What is missing? More HTTP (verbs, status codes, headers) Wednesday, June 9, 2010
  • 80. What is missing? More HTTP (verbs, status codes, headers) Hyperlinks Wednesday, June 9, 2010
  • 81. What is missing? More HTTP (verbs, status codes, headers) Hyperlinks Semantic (media-types) Wednesday, June 9, 2010
  • 82. GET POST PUT DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 83. GET POST POST DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 84. GET POST PATCH DELETE nd create update destroy SELECT INSERT UPDATE DELETE Wednesday, June 9, 2010
  • 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
  • 87. Why bother? Consistency Wednesday, June 9, 2010
  • 88. Why bother? Consistency Simplicity Wednesday, June 9, 2010
  • 89. Why bother? Consistency Simplicity Discoverability Wednesday, June 9, 2010
  • 90. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  • 91. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  • 92. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  • 93. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  • 94. The Web as it is Wednesday, June 9, 2010
  • 95. The Web as it is Wednesday, June 9, 2010
  • 97. Evaluation Workflow When there is a new app Wednesday, June 9, 2010
  • 98. Evaluation Workflow When there is a new app Then move forward to evaluate it Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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
  • 116. The Automated Web? ? Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  • 129. No Mechanization? Hyperlinks Wednesday, June 9, 2010
  • 130. No Mechanization? Hyperlinks No Semantics Wednesday, June 9, 2010
  • 131. No Mechanization? Hyperlinks No Semantics Human Heuristics Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. <?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
  • 147. Why not ActiveResource? No Hyperlinks Wednesday, June 9, 2010
  • 148. Why not ActiveResource? No Hyperlinks No Semantics Wednesday, June 9, 2010
  • 149. Why not ActiveResource? No Hyperlinks No Semantics Doesn’t respect HTTP (etag, last modi ed) Wednesday, June 9, 2010
  • 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. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Wednesday, June 9, 2010
  • 152. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Most are not really “REST” Wednesday, June 9, 2010
  • 153. Why not other web clients? HTTParty, RestClient, Typhoeus, Curb Most are not really “REST” Just URI consumers Wednesday, June 9, 2010
  • 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. One goal is to avoid tight coupling Wednesday, June 9, 2010
  • 158. Restfulie Client and Server solution Wednesday, June 9, 2010
  • 159. Restfulie Client and Server solution XML, JSON, Atom Representations Wednesday, June 9, 2010
  • 160. Restfulie Client and Server solution XML, JSON, Atom Representations Enhances Ruby on Rails Wednesday, June 9, 2010
  • 161. Restfulie Client and Server solution XML, JSON, Atom Representations Enhances Ruby on Rails REST Client Wednesday, June 9, 2010
  • 162. Restfulie @guilhermesilveira @caueguerra @georgeguimaraes @lfcipriani Wednesday, June 9, 2010
  • 163. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  • 164. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  • 165. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  • 166. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  • 167. class AppsController < ApplicationController restfulie respond_to :html, :xml, :atom inherit_resources ... end app/controllers/apps_controller.rb Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. <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. <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. <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. <?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. <?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. <?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
  • 185. Mechanizable Web Hyperlinks Wednesday, June 9, 2010
  • 186. Mechanizable Web Hyperlinks Link Relations Wednesday, June 9, 2010
  • 187. Mechanizable Web Hyperlinks Link Relations Media Types Wednesday, June 9, 2010
  • 188. Mechanizable Web Hyperlinks Link Relations Media Types Domain Application Protocol (DAP) Wednesday, June 9, 2010
  • 189. Mechanizable Web Hyperlinks Link Relations Media Types Domain Application Protocol (DAP) HATEOAS Wednesday, June 9, 2010
  • 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. Contract Protocols Wednesday, June 9, 2010
  • 192. Protocol HTTP idioms Media Types Entry-point URIs Contract Protocols Wednesday, June 9, 2010
  • 193. Media Type Formats Link Relations Processing Models Schema Protocol HTTP idioms Media Types Entry-point URIs Contract Protocols Wednesday, June 9, 2010
  • 195. Improving Restfulie Single interface for representations Wednesday, June 9, 2010
  • 196. Improving Restfulie Single interface for representations Smart defaults for serialization Wednesday, June 9, 2010
  • 197. Improving Restfulie Single interface for representations Smart defaults for serialization XML serialization compatible with Rails Wednesday, June 9, 2010
  • 198. Improving Restfulie Single interface for representations Smart defaults for serialization XML serialization compatible with Rails Rails 3 compatibility Wednesday, June 9, 2010
  • 200. One more thing Wednesday, June 9, 2010
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. EvaluationProcess.run http://bit.ly/railsconf2010-restfulie Wednesday, June 9, 2010
  • 213. Adaptable Client Goal Oriented Wednesday, June 9, 2010
  • 214. Adaptable Client Goal Oriented Pattern Matching Wednesday, June 9, 2010
  • 215. Adaptable Client Goal Oriented Pattern Matching Can adapt to some changes Wednesday, June 9, 2010
  • 216. Richardson Restful Model Level 3 Hypermedia Level 2 HTTP Level 1 URI Wednesday, June 9, 2010
  • 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. We’re not done yet! Wednesday, June 9, 2010
  • 220. Thank you! @AkitaOnRails http://bit.ly/railsconf2010-restfulie Wednesday, June 9, 2010