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

What's hot

Radio And Satellite Navigation
Radio And Satellite NavigationRadio And Satellite Navigation
Radio And Satellite Navigationwillmac1wm
 
GPRS(General Packet Radio Service)
GPRS(General Packet Radio Service)GPRS(General Packet Radio Service)
GPRS(General Packet Radio Service)Jay Nagar
 
Quick reference guide ans
Quick reference guide  ansQuick reference guide  ans
Quick reference guide ansZameer Basha
 
1 radar basic - part ii
1 radar basic - part ii1 radar basic - part ii
1 radar basic - part iiSolo Hermelin
 
Radar 2009 a 10 radar clutter1
Radar 2009 a 10 radar clutter1Radar 2009 a 10 radar clutter1
Radar 2009 a 10 radar clutter1Forward2025
 
Protocols for wireless sensor networks
Protocols for wireless sensor networks Protocols for wireless sensor networks
Protocols for wireless sensor networks DEBABRATASINGH3
 
Link budget
Link budgetLink budget
Link budgetdrmbalu
 
How Mobile Technology Works
How Mobile Technology WorksHow Mobile Technology Works
How Mobile Technology Works3G4G
 
Wireless communication by abhishek mmahajan
Wireless communication by abhishek mmahajanWireless communication by abhishek mmahajan
Wireless communication by abhishek mmahajanAbhishek Mahajan
 
Overview of handover decision strategies in heterogeneous networks by narendr...
Overview of handover decision strategies in heterogeneous networks by narendr...Overview of handover decision strategies in heterogeneous networks by narendr...
Overview of handover decision strategies in heterogeneous networks by narendr...Narendra Prajapati
 
Lte(long term evolution) 4G LTE
Lte(long term evolution) 4G LTELte(long term evolution) 4G LTE
Lte(long term evolution) 4G LTEkaishik gundu
 
Secondary Surveillance Radar, Mode-S and ADS-B
Secondary Surveillance Radar, Mode-S and ADS-BSecondary Surveillance Radar, Mode-S and ADS-B
Secondary Surveillance Radar, Mode-S and ADS-BAjay Kumar Singh
 
Ofdm tutorial fuyun_ling_rev1
Ofdm tutorial fuyun_ling_rev1Ofdm tutorial fuyun_ling_rev1
Ofdm tutorial fuyun_ling_rev1Fuyun Ling
 
Brief introduction to satellite communications
Brief introduction to satellite communicationsBrief introduction to satellite communications
Brief introduction to satellite communicationsSally Sheridan
 

What's hot (20)

Radio And Satellite Navigation
Radio And Satellite NavigationRadio And Satellite Navigation
Radio And Satellite Navigation
 
GPRS(General Packet Radio Service)
GPRS(General Packet Radio Service)GPRS(General Packet Radio Service)
GPRS(General Packet Radio Service)
 
Quick reference guide ans
Quick reference guide  ansQuick reference guide  ans
Quick reference guide ans
 
1 radar basic - part ii
1 radar basic - part ii1 radar basic - part ii
1 radar basic - part ii
 
Radar 2009 a 10 radar clutter1
Radar 2009 a 10 radar clutter1Radar 2009 a 10 radar clutter1
Radar 2009 a 10 radar clutter1
 
Protocols for wireless sensor networks
Protocols for wireless sensor networks Protocols for wireless sensor networks
Protocols for wireless sensor networks
 
Unit 1 sc
Unit 1 scUnit 1 sc
Unit 1 sc
 
Link budget
Link budgetLink budget
Link budget
 
Satellite systems in communication
Satellite systems in communicationSatellite systems in communication
Satellite systems in communication
 
TT&C subsystem
TT&C subsystemTT&C subsystem
TT&C subsystem
 
How Mobile Technology Works
How Mobile Technology WorksHow Mobile Technology Works
How Mobile Technology Works
 
Wireless communication by abhishek mmahajan
Wireless communication by abhishek mmahajanWireless communication by abhishek mmahajan
Wireless communication by abhishek mmahajan
 
Data dissemination
Data disseminationData dissemination
Data dissemination
 
Overview of handover decision strategies in heterogeneous networks by narendr...
Overview of handover decision strategies in heterogeneous networks by narendr...Overview of handover decision strategies in heterogeneous networks by narendr...
Overview of handover decision strategies in heterogeneous networks by narendr...
 
Lte(long term evolution) 4G LTE
Lte(long term evolution) 4G LTELte(long term evolution) 4G LTE
Lte(long term evolution) 4G LTE
 
Ch3
Ch3Ch3
Ch3
 
Secondary Surveillance Radar, Mode-S and ADS-B
Secondary Surveillance Radar, Mode-S and ADS-BSecondary Surveillance Radar, Mode-S and ADS-B
Secondary Surveillance Radar, Mode-S and ADS-B
 
Ofdm tutorial fuyun_ling_rev1
Ofdm tutorial fuyun_ling_rev1Ofdm tutorial fuyun_ling_rev1
Ofdm tutorial fuyun_ling_rev1
 
Satellite Communication Theory
Satellite  Communication TheorySatellite  Communication Theory
Satellite Communication Theory
 
Brief introduction to satellite communications
Brief introduction to satellite communicationsBrief introduction to satellite communications
Brief introduction to satellite communications
 

Viewers also liked

Low Friction Personal Data Collection - CyborgCamp 2012
Low Friction Personal Data Collection - CyborgCamp 2012Low Friction Personal Data Collection - CyborgCamp 2012
Low Friction Personal Data Collection - CyborgCamp 2012Aaron Parecki
 
Dom Sagolla - Cumbre del Futuro 2010
Dom Sagolla - Cumbre del Futuro 2010Dom Sagolla - Cumbre del Futuro 2010
Dom Sagolla - Cumbre del Futuro 2010La Nación
 
Google App Engine for Business - Sydney Devfest
Google App Engine for Business - Sydney DevfestGoogle App Engine for Business - Sydney Devfest
Google App Engine for Business - Sydney DevfestPatrick Chanezon
 
Mediastyle Media Training
Mediastyle Media TrainingMediastyle Media Training
Mediastyle Media TrainingIan Capstick
 
Growing Your Email Audience (Blue Sky Factory User Conference)
Growing Your Email Audience (Blue Sky Factory User Conference)Growing Your Email Audience (Blue Sky Factory User Conference)
Growing Your Email Audience (Blue Sky Factory User Conference)Blue Sky Factory
 
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013Aaron Parecki
 

Viewers also liked (9)

Low Friction Personal Data Collection - CyborgCamp 2012
Low Friction Personal Data Collection - CyborgCamp 2012Low Friction Personal Data Collection - CyborgCamp 2012
Low Friction Personal Data Collection - CyborgCamp 2012
 
Art
ArtArt
Art
 
Iphoto
IphotoIphoto
Iphoto
 
Dom Sagolla - Cumbre del Futuro 2010
Dom Sagolla - Cumbre del Futuro 2010Dom Sagolla - Cumbre del Futuro 2010
Dom Sagolla - Cumbre del Futuro 2010
 
You and youtube
You and youtubeYou and youtube
You and youtube
 
Google App Engine for Business - Sydney Devfest
Google App Engine for Business - Sydney DevfestGoogle App Engine for Business - Sydney Devfest
Google App Engine for Business - Sydney Devfest
 
Mediastyle Media Training
Mediastyle Media TrainingMediastyle Media Training
Mediastyle Media Training
 
Growing Your Email Audience (Blue Sky Factory User Conference)
Growing Your Email Audience (Blue Sky Factory User Conference)Growing Your Email Audience (Blue Sky Factory User Conference)
Growing Your Email Audience (Blue Sky Factory User Conference)
 
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013
Deep Dive into the ArcGIS Geotrigger Service - Esri DevSummit Dubai 2013
 

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

Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfDianaGray10
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 

Recently uploaded (20)

Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdfUiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
UiPath Solutions Management Preview - Northern CA Chapter - March 22.pdf
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 

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