REST & ActiveResource
      Matthijs Langenberg
Webservices
Wat zijn webservices
”The W3C defines a Web Service as a software system designed to support
     interoperable machine to machine interaction o...
Bevorder ‘machine to machine interaction’
HTML is moeilijk te parsen
Geef iets anders terug

        XML?
Just Another View
respond_to
class ArticlesController < ApplicationController
 def show
    @article = Article.find(params[:id])
    respond_to do |for...
Soorten Webservices

• Remote procedure calls (RPC)
• Service-oriented architecture (SOA)
• Representational state transfe...
Rails votes REST
Rails votes REST

   BIG TIME!
Wat is REST?
REpresentional State Transfer
HTTP’s:
“convention over configuration”
Schreef geen vervanging voor iets wat HTTP je gratis geeft
HTTP Abuse
Wat is er mis met dit request?
  GET http://myblog.com/articles/destroy/1
HTTP Abuse
Wat is er mis met dit request?
  GET http://myblog.com/articles/destroy/1



                     Conflict
HTTP Abuse
Wat is er mis met dit request?
  GET http://myblog.com/articles/destroy/1



                     Conflict

• Ac...
The REST-way


DELETE http://myblog.com/articles/1
URI’s
URI’s

GET /articles/create

GET /articles/show/1

GET /articles/update/1

GET /articles/destroy/1
URI’s

GET /articles/create

GET /articles/show/1

GET /articles/update/1

GET /articles/destroy/1
Mapping
Mapping

HTTP

 GET

POST

 PUT

DELETE
Mapping

HTTP     Controller

 GET      SHOW

POST      CREATE

 PUT      UPDATE

DELETE   DESTROY
Resourceful URI’s
Resourceful URI’s

GET /articles

POST /articles/create

GET /articles/show/1

POST /articles/update/1

GET /articles/dest...
Resourceful URI’s

                          ➡   GET /articles
GET /articles

                          ➡   POST /articles...
Gratis named routes
ActionController::Routing::Routes.draw do |map|
  map.resources :articles do |articles|
    articles.resources :comments
 ...
ActionController::Routing::Routes.draw do |map|
  map.resources :articles do |articles|
    articles.resources :comments
 ...
ActionController::Routing::Routes.draw do |map|
     map.resources :articles do |articles|
       articles.resources :comm...
ActionController::Routing::Routes.draw do |map|
     map.resources :articles do |articles|
       articles.resources :comm...
link_to article.title,

 { 
:controller => ‘article’,
    
 :action => ‘show’,

 
 :id => article }
link_to article.title,

 { 
:controller => ‘article’,
    
 :action => ‘show’,

 
 :id => article }
link_to article.title,
     
 { 
:controller => ‘article’,
         
 :action => ‘show’,
     
 
 :id => article }




lin...
link_to article.title,
     
 { 
:controller => ‘article’,
         
 :action => ‘show’,
     
 
 :id => article }




lin...
Wat zou je doen?
Je wilt comments aan articles toevoegen,
ArticlesController is aanwezig.
Wat zou je doen?
        Je wilt comments aan articles toevoegen,
        ArticlesController is aanwezig.


1) Voeg een ac...
Wat zou je doen?
        Je wilt comments aan articles toevoegen,
        ArticlesController is aanwezig.


1) Voeg een ac...
Mr. RESTful zegt:
Mr. RESTful zegt:
     Antwoord 2
Mr. RESTful zegt:
                    Antwoord 2


• Een comment is een een aparte resource
Mr. RESTful zegt:
                   Antwoord 2


• Een comment is een een aparte resource
• Er bestaat geen ‘add_comment’...
Mr. RESTful zegt:
                    Antwoord 2


• Een comment is een een aparte resource
• Er bestaat geen ‘add_comment...
Geen Namespaces!

•   POST /articles/create

•   POST /articles/create_comment

•   GET /articles/destroy

•   GET /articl...
Teveel vrijheid is niet goed
class ArticlesController < ApplicationController
 def show
   @article = Article.find(params[:id])
 end

 def show_rss
   ...
Geen aparte actie voor alternatieve view!
class ArticlesController < ApplicationController
 def show
    @article = Article.find(params[:id])
    respond_to do |for...
Wauw!
HTTP method naar controller actie mapping actie klinkt tof!
Maar er zit een adder ...
Maar er zit een adder ...
Browsers ondersteunen PUT en DELETE niet!
Browsers ondersteunen PUT en DELETE niet!

<input name=quot;_methodquot; type=quot;hiddenquot; value=quot;putquot; />
Gelukkig zijn de helpers ook
       aangepast. ;-)
HTML_options


•   link_to “delete”, article_path(1), :method => ‘delete’

•   link_to_remote, “delete”, article_path(1), ...
form_for
              remote_form_for
Bepalen op basis van AR object de method:
  form_for(Movie.new):

  <form action=qu...
Controller Acties
MoviesController#index
MoviesController#index
# GET /movies
# GET /movies.xml
def index
 @movies = Movie.find(:all)

 respond_to do |format|
  for...
MoviesController#index
                                          <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
# ...
MoviesController#show
MoviesController#show
# GET /movies/1
# GET /movies/1.xml
def show
 @movie = Movie.find(params[:id])

 respond_to do |forma...
MoviesController#show
# GET /movies/1                          <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
    ...
MoviesController#create
MoviesController#create
# POST /movies
# POST /movies.xml
def create
 @movie = Movie.new(params[:movie])

 respond_to do |...
MoviesController#create
                                                                  Status: 201 Created
            ...
MoviesController#create
                                                                  Status: 201 Created
            ...
MoviesController#update
MoviesController#update
# PUT /movies/1
# PUT /movies/1.xml
def update
 @movie = Movie.find(params[:id])

 respond_to do |f...
MoviesController#update
                                                                  Status: 200 OK
# PUT /movies/1
#...
MoviesController#update
                                                                  Status: 200 OK
# PUT /movies/1
#...
MoviesController#destroy
MoviesController#destroy

# DELETE /movies/1
# DELETE /movies/1.xml
def destroy
 @movie = Movie.find(params[:id])
 @movie.d...
MoviesController#destroy

# DELETE /movies/1                          Status: 200 OK
# DELETE /movies/1.xml
def destroy
 @...
Scaffolding
maar er is meer!
ActiveResource
ActiveResource


•   Object-oriented REST services

•   Transparent met een RESTful service (Rails) werken

•   Net als Ac...
Browser
Browser


      GET /movies.html


Controller
(RESTful)
Browser


       GET /movies.html


 Controller
 (RESTful)

        Movie.find(:all)


ActiveRecord
Browser


       GET /movies.html


 Controller
 (RESTful)

         Movie.find(:all)


ActiveRecord

       SELECT * FROM ...
Browser     Browser


                 GET /movies.html


           Controller
           (RESTful)

                   M...
Browser                   Browser


      GET /movies.html          GET /movies.html


                          Controlle...
Browser                   Browser


        GET /movies.html          GET /movies.html


                            Contr...
Browser                                    Browser


        GET /movies.html                           GET /movies.html

...
Configuratie
Werken met RESTful webservices
      (ActiveResource)
Create
Create
Read
Read
Update
Update
Destroy
Destroy
Wat doet ARes?
Wat doet ARes?

• Genereer URL
Wat doet ARes?

• Genereer URL
• Request URL (XML)
Wat doet ARes?

• Genereer URL
• Request URL (XML)
• Verwerk request (XML)
Wat doet ARes?

• Genereer URL
• Request URL (XML)
• Verwerk request (XML)
• Biedt ActiveRecord-like API
Demo
Demo

1) RESTful Rails applicatie (met curl)
Demo

1) RESTful Rails applicatie (met curl)
2) Rails applicatie met ActiveResource
Demo

1) RESTful Rails applicatie (met curl)
2) Rails applicatie met ActiveResource
3) ActiveResource gem
Vragen?

 <mlangenberg@gmail.com>
#rubyenrails at irc.freenode.org
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
ActiveResource & REST
Upcoming SlideShare
Loading in …5
×

ActiveResource & REST

3,042 views

Published on

Matthijs Langenberg's slide's of his presentation at the RubyenRails 2007 conf in Amsterdam.

Published in: Technology, Design
  • Be the first to comment

ActiveResource & REST

  1. 1. REST & ActiveResource Matthijs Langenberg
  2. 2. Webservices
  3. 3. Wat zijn webservices
  4. 4. ”The W3C defines a Web Service as a software system designed to support interoperable machine to machine interaction over a network.” -- Wikipedia
  5. 5. Bevorder ‘machine to machine interaction’
  6. 6. HTML is moeilijk te parsen
  7. 7. Geef iets anders terug XML?
  8. 8. Just Another View
  9. 9. respond_to
  10. 10. class ArticlesController < ApplicationController def show @article = Article.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @article } end end end
  11. 11. Soorten Webservices • Remote procedure calls (RPC) • Service-oriented architecture (SOA) • Representational state transfer (REST)
  12. 12. Rails votes REST
  13. 13. Rails votes REST BIG TIME!
  14. 14. Wat is REST?
  15. 15. REpresentional State Transfer
  16. 16. HTTP’s: “convention over configuration”
  17. 17. Schreef geen vervanging voor iets wat HTTP je gratis geeft
  18. 18. HTTP Abuse Wat is er mis met dit request? GET http://myblog.com/articles/destroy/1
  19. 19. HTTP Abuse Wat is er mis met dit request? GET http://myblog.com/articles/destroy/1 Conflict
  20. 20. HTTP Abuse Wat is er mis met dit request? GET http://myblog.com/articles/destroy/1 Conflict • Actie staat in URL • Uitgevoerd actie is in conflict met HTTP methode
  21. 21. The REST-way DELETE http://myblog.com/articles/1
  22. 22. URI’s
  23. 23. URI’s GET /articles/create GET /articles/show/1 GET /articles/update/1 GET /articles/destroy/1
  24. 24. URI’s GET /articles/create GET /articles/show/1 GET /articles/update/1 GET /articles/destroy/1
  25. 25. Mapping
  26. 26. Mapping HTTP GET POST PUT DELETE
  27. 27. Mapping HTTP Controller GET SHOW POST CREATE PUT UPDATE DELETE DESTROY
  28. 28. Resourceful URI’s
  29. 29. Resourceful URI’s GET /articles POST /articles/create GET /articles/show/1 POST /articles/update/1 GET /articles/destroy/1
  30. 30. Resourceful URI’s ➡ GET /articles GET /articles ➡ POST /articles POST /articles/create ➡ GET /articles/1 GET /articles/show/1 ➡ PUT /articles/1 POST /articles/update/1 ➡ DELETE /articles/1 GET /articles/destroy/1
  31. 31. Gratis named routes
  32. 32. ActionController::Routing::Routes.draw do |map| map.resources :articles do |articles| articles.resources :comments end end
  33. 33. ActionController::Routing::Routes.draw do |map| map.resources :articles do |articles| articles.resources :comments end end
  34. 34. ActionController::Routing::Routes.draw do |map| map.resources :articles do |articles| articles.resources :comments end end articles_url article_url new_article_url edit_article_url article_comments_url article_comment_url article_new_comment_url article_edit_comment_url
  35. 35. ActionController::Routing::Routes.draw do |map| map.resources :articles do |articles| articles.resources :comments end end articles_url ➡ /articles article_url ➡ /articles/:id new_article_url ➡ /articles/new edit_article_url ➡ /articles/:id/edit article_comments_url ➡ /articles/:article_id/comments article_comment_url ➡ /articles/:article_id/comments/:id article_new_comment_url ➡ /articles/:article_id/comments/new article_edit_comment_url ➡ /articles/:article_id/comments/:id/edit
  36. 36. link_to article.title, { :controller => ‘article’, :action => ‘show’, :id => article }
  37. 37. link_to article.title, { :controller => ‘article’, :action => ‘show’, :id => article }
  38. 38. link_to article.title, { :controller => ‘article’, :action => ‘show’, :id => article } link_to article.title, article_url(article)
  39. 39. link_to article.title, { :controller => ‘article’, :action => ‘show’, :id => article } link_to article.title, article_url(article) link_to article.title, article
  40. 40. Wat zou je doen? Je wilt comments aan articles toevoegen, ArticlesController is aanwezig.
  41. 41. Wat zou je doen? Je wilt comments aan articles toevoegen, ArticlesController is aanwezig. 1) Voeg een actie ‘add_comment’ aan ArticlesController toe. (POST /articles/1/add_comment)
  42. 42. Wat zou je doen? Je wilt comments aan articles toevoegen, ArticlesController is aanwezig. 1) Voeg een actie ‘add_comment’ aan ArticlesController toe. (POST /articles/1/add_comment) 2) Maak een CommentsController, met een ‘create’ actie. (POST /comments/create?article_id=1)
  43. 43. Mr. RESTful zegt:
  44. 44. Mr. RESTful zegt: Antwoord 2
  45. 45. Mr. RESTful zegt: Antwoord 2 • Een comment is een een aparte resource
  46. 46. Mr. RESTful zegt: Antwoord 2 • Een comment is een een aparte resource • Er bestaat geen ‘add_comment’ methode in HTTP
  47. 47. Mr. RESTful zegt: Antwoord 2 • Een comment is een een aparte resource • Er bestaat geen ‘add_comment’ methode in HTTP • Er bestaat wel een ‘create’ (POST) methode in HTTP
  48. 48. Geen Namespaces! • POST /articles/create • POST /articles/create_comment • GET /articles/destroy • GET /articles/destroy_comment
  49. 49. Teveel vrijheid is niet goed
  50. 50. class ArticlesController < ApplicationController def show @article = Article.find(params[:id]) end def show_rss @article = Article.find(params[:id]) render :rss => @article.to_rss end def show_atom @article = Article.find(params[:id]) render :atom => @article.to_atom end def show_xml @article = Article.find(params[:id]) render :xml => @article.to_xml end def show_ajax @article = Article.find(params[:id]) render :template => show_article.rjs end end
  51. 51. Geen aparte actie voor alternatieve view!
  52. 52. class ArticlesController < ApplicationController def show @article = Article.find(params[:id]) respond_to do |format| format.html format.rss { render :rss => @article.to_rss } format.atom { render :atom => @article.to_atom } format.xml { render :xml => @article.to_xml } format.rjs { render :template => ‘show_article.rjs’ } end end end
  53. 53. Wauw! HTTP method naar controller actie mapping actie klinkt tof!
  54. 54. Maar er zit een adder ...
  55. 55. Maar er zit een adder ...
  56. 56. Browsers ondersteunen PUT en DELETE niet!
  57. 57. Browsers ondersteunen PUT en DELETE niet! <input name=quot;_methodquot; type=quot;hiddenquot; value=quot;putquot; />
  58. 58. Gelukkig zijn de helpers ook aangepast. ;-)
  59. 59. HTML_options • link_to “delete”, article_path(1), :method => ‘delete’ • link_to_remote, “delete”, article_path(1), :method => ‘delete’ • form_tag(member_path(2), :method => :put)
  60. 60. form_for remote_form_for Bepalen op basis van AR object de method: form_for(Movie.new): <form action=quot;/moviesquot; class=quot;new_moviequot; id=quot;new_moviequot; method=quot;postquot;> form_for(Movie.find(:first)): <form action=quot;/movies/1quot; class=quot;edit_moviequot; id=quot;edit_movie_1quot; method=quot;postquot;> <input name=quot;_methodquot; type=quot;hiddenquot; value=quot;putquot; />
  61. 61. Controller Acties
  62. 62. MoviesController#index
  63. 63. MoviesController#index # GET /movies # GET /movies.xml def index @movies = Movie.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @movies } end end
  64. 64. MoviesController#index <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> # GET /movies <movies> # GET /movies.xml <movie> def index <director>Chris Miller</director> @movies = Movie.find(:all) <id type=quot;integerquot;>1</id> <rating type=quot;decimalquot;>7.0</rating> respond_to do |format| <title>Shrek the Third</title> format.html # index.html.erb </movie> <movie> format.xml { render :xml => @movies } <director>Sam Raimi</director> end <id type=quot;integerquot;>2</id> end <rating type=quot;decimalquot;>6.9</rating> <title>Spider-Man 3</title> </movie> <movie> <director>Juan Carlos Fresnadillo</director> <id type=quot;integerquot;>3</id> <rating type=quot;decimalquot;>7.7</rating> <title>28 Weeks Later</title> </movie> </movies>
  65. 65. MoviesController#show
  66. 66. MoviesController#show # GET /movies/1 # GET /movies/1.xml def show @movie = Movie.find(params[:id]) respond_to do |format| format.html # show.html.erb format.xml { render :xml => @movie } end end
  67. 67. MoviesController#show # GET /movies/1 <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <movie> # GET /movies/1.xml <director>Chris Miller</director> def show <id type=quot;integerquot;>1</id> @movie = Movie.find(params[:id]) <rating type=quot;decimalquot;>7.0</rating> <title>Shrek the Third</title> respond_to do |format| </movie> format.html # show.html.erb format.xml { render :xml => @movie } end end
  68. 68. MoviesController#create
  69. 69. MoviesController#create # POST /movies # POST /movies.xml def create @movie = Movie.new(params[:movie]) respond_to do |format| if @movie.save flash[:notice] = 'Movie was successfully created.' format.html { redirect_to(@movie) } format.xml { render :xml => @movie, :status => :created, :location => @movie } else format.html { render :action => quot;newquot; } format.xml { render :xml => @movie.errors, :status => 422 } end end end
  70. 70. MoviesController#create Status: 201 Created Location: http://localhost:3000/movies/16 # POST /movies <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> # POST /movies.xml <movie> def create <director>Steven Spielbergh</director> @movie = Movie.new(params[:movie]) <id type=quot;integerquot;>15</id> <rating type=quot;decimalquot;>8.3</rating> respond_to do |format| <title>Letters from Iwo Jima</title> if @movie.save </movie> flash[:notice] = 'Movie was successfully created.' format.html { redirect_to(@movie) } format.xml { render :xml => @movie, :status => :created, :location => @movie } else format.html { render :action => quot;newquot; } format.xml { render :xml => @movie.errors, :status => 422 } end end end
  71. 71. MoviesController#create Status: 201 Created Location: http://localhost:3000/movies/16 # POST /movies <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> # POST /movies.xml <movie> def create <director>Steven Spielbergh</director> @movie = Movie.new(params[:movie]) <id type=quot;integerquot;>15</id> <rating type=quot;decimalquot;>8.3</rating> respond_to do |format| <title>Letters from Iwo Jima</title> if @movie.save </movie> flash[:notice] = 'Movie was successfully created.' format.html { redirect_to(@movie) } format.xml { render :xml => @movie, :status => :created, Status: 422 Unprocessable Entity :location => @movie } <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> else <errors> format.html { render :action => quot;newquot; } <error>Rating can't be blank</error> format.xml { render :xml => @movie.errors, :status => 422 } <error>Director can't be blank</error> end <error>Title can't be blank</error> end </errors> end
  72. 72. MoviesController#update
  73. 73. MoviesController#update # PUT /movies/1 # PUT /movies/1.xml def update @movie = Movie.find(params[:id]) respond_to do |format| if @movie.update_attributes(params[:movie]) flash[:notice] = 'Movie was successfully updated.' format.html { redirect_to(@movie) } format.xml { head :ok } else format.html { render :action => quot;editquot; } format.xml { render :xml => @movie.errors, :status => 422 } end end end
  74. 74. MoviesController#update Status: 200 OK # PUT /movies/1 # PUT /movies/1.xml def update @movie = Movie.find(params[:id]) respond_to do |format| if @movie.update_attributes(params[:movie]) flash[:notice] = 'Movie was successfully updated.' format.html { redirect_to(@movie) } format.xml { head :ok } else format.html { render :action => quot;editquot; } format.xml { render :xml => @movie.errors, :status => 422 } end end end
  75. 75. MoviesController#update Status: 200 OK # PUT /movies/1 # PUT /movies/1.xml def update @movie = Movie.find(params[:id]) Status: 422 Unprocessable Entity respond_to do |format| <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> if @movie.update_attributes(params[:movie]) <errors> flash[:notice] = 'Movie was successfully updated.' <error>Title can't be blank</error> format.html { redirect_to(@movie) } </errors> format.xml { head :ok } else format.html { render :action => quot;editquot; } format.xml { render :xml => @movie.errors, :status => 422 } end end end
  76. 76. MoviesController#destroy
  77. 77. MoviesController#destroy # DELETE /movies/1 # DELETE /movies/1.xml def destroy @movie = Movie.find(params[:id]) @movie.destroy respond_to do |format| format.html { redirect_to(movies_url) } format.xml { head :ok } end end
  78. 78. MoviesController#destroy # DELETE /movies/1 Status: 200 OK # DELETE /movies/1.xml def destroy @movie = Movie.find(params[:id]) @movie.destroy respond_to do |format| format.html { redirect_to(movies_url) } format.xml { head :ok } end end
  79. 79. Scaffolding
  80. 80. maar er is meer!
  81. 81. ActiveResource
  82. 82. ActiveResource • Object-oriented REST services • Transparent met een RESTful service (Rails) werken • Net als ActiveRecord, maar dan voor REST
  83. 83. Browser
  84. 84. Browser GET /movies.html Controller (RESTful)
  85. 85. Browser GET /movies.html Controller (RESTful) Movie.find(:all) ActiveRecord
  86. 86. Browser GET /movies.html Controller (RESTful) Movie.find(:all) ActiveRecord SELECT * FROM MOVIES DB
  87. 87. Browser Browser GET /movies.html Controller (RESTful) Movie.find(:all) ActiveRecord SELECT * FROM MOVIES DB
  88. 88. Browser Browser GET /movies.html GET /movies.html Controller Controller (RESTful) Movie.find(:all) ActiveRecord SELECT * FROM MOVIES DB
  89. 89. Browser Browser GET /movies.html GET /movies.html Controller Controller (RESTful) Movie.find(:all) Movie.find(:all) ActiveResource ActiveRecord SELECT * FROM MOVIES DB
  90. 90. Browser Browser GET /movies.html GET /movies.html Controller Controller (RESTful) Movie.find(:all) Movie.find(:all) GET /movies.xml ActiveResource ActiveRecord SELECT * FROM MOVIES DB
  91. 91. Configuratie
  92. 92. Werken met RESTful webservices (ActiveResource)
  93. 93. Create
  94. 94. Create
  95. 95. Read
  96. 96. Read
  97. 97. Update
  98. 98. Update
  99. 99. Destroy
  100. 100. Destroy
  101. 101. Wat doet ARes?
  102. 102. Wat doet ARes? • Genereer URL
  103. 103. Wat doet ARes? • Genereer URL • Request URL (XML)
  104. 104. Wat doet ARes? • Genereer URL • Request URL (XML) • Verwerk request (XML)
  105. 105. Wat doet ARes? • Genereer URL • Request URL (XML) • Verwerk request (XML) • Biedt ActiveRecord-like API
  106. 106. Demo
  107. 107. Demo 1) RESTful Rails applicatie (met curl)
  108. 108. Demo 1) RESTful Rails applicatie (met curl) 2) Rails applicatie met ActiveResource
  109. 109. Demo 1) RESTful Rails applicatie (met curl) 2) Rails applicatie met ActiveResource 3) ActiveResource gem
  110. 110. Vragen? <mlangenberg@gmail.com> #rubyenrails at irc.freenode.org

×