Making Rails Really restful
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Making Rails Really restful

on

  • 10,357 views

 

Statistics

Views

Total Views
10,357
Views on SlideShare
7,953
Embed Views
2,404

Actions

Likes
31
Downloads
206
Comments
1

22 Embeds 2,404

http://www.akitaonrails.com 1158
http://akitaonrails.com 796
http://www.slideshare.net 177
http://en.oreilly.com 104
http://localhost 79
http://www.infoblogs.com.br 51
http://www.rubyonrails.pro.br 7
http://www.akitaonrails.com.br 5
http://twitter.com 5
http://translate.googleusercontent.com 4
http://www.fabioakita.com 4
http://akitaonrails.com.br 3
http://forum.rubyonbr.org 2
http://www.rails.com.br 1
https://twitter.com 1
http://seekr-artemis.heroku.com 1
http://tweetedtimes.com 1
http://facebook.slideshare.com 1
http://infoblogs.com.br 1
http://fabioakita.com 1
http://www.plugmasters.com.br 1
http://www.google.com.br 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • CRUD through HTTP is a good step forward to using resources and becoming RESTful, another step further is to make use of hypermedia aware resources and Restfulie allows you to do it in Java and Ruby.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Making Rails Really restful Presentation Transcript

  • 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
  • 8. 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
  • 16. 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
  • 49. But! 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
  • 60. REST Principles 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
  • 65. REST Goals 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
  • 72. 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
  • 78. What is missing? 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
  • 86. Why bother? 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
  • 96. Evaluation Workflow 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
  • 105. Wednesday, June 9, 2010
  • 106. Wednesday, June 9, 2010
  • 107. Wednesday, June 9, 2010
  • 108. Wednesday, June 9, 2010
  • 109. Wednesday, June 9, 2010
  • 110. Wednesday, June 9, 2010
  • 111. Wednesday, June 9, 2010
  • 112. Wednesday, June 9, 2010
  • 113. Wednesday, June 9, 2010
  • 114. Wednesday, June 9, 2010
  • 115. The Automated Web? 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
  • 128. No Mechanization? 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
  • 146. Why not ActiveResource? 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
  • 156. http://restfulie.caelumobjects.com/ Wednesday, June 9, 2010
  • 157. Restfulie 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
  • 168. Tokamak Wednesday, June 9, 2010
  • 169. Tokamak 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
  • 184. Mechanizable Web 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
  • 194. Improving Restfulie 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
  • 199. Wednesday, June 9, 2010
  • 200. One more thing Wednesday, June 9, 2010
  • 201. Mikyung 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
  • 212. Adaptable Client 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
  • 219. Wednesday, June 9, 2010
  • 220. Thank you! @AkitaOnRails http://bit.ly/railsconf2010-restfulie Wednesday, June 9, 2010