Sinatra for REST services

11,071 views
10,606 views

Published on

Introduction to Sinatra miniframework. This talk was given at the @Webnetconf in Milan 2012.

Published in: Technology
0 Comments
13 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,071
On SlideShare
0
From Embeds
0
Number of Embeds
31
Actions
Shares
0
Downloads
93
Comments
0
Likes
13
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Sinatra for REST services

    1. 1. REST with Sinatra Emanuele DelBono @emadb
    2. 2. Thanks to the sponsors
    3. 3. About meI’m a software developer inCodicePlastico.I write Web applications in C# withASP.NET MVC. I’m a member of<WEBdeBS/> a local webcommunity....and I’m a wannabe Rubydeveloper ;-)
    4. 4. Agenda‣ Philosophy. Sweet and easy.‣ REST. Yet another boring introduction.‣ Hello world. Show some magic.‣ Features. Amazing!‣ Inside. How it works?‣ Q&A. ...and thanks.
    5. 5. Sinatra as a REST server
    6. 6. What is isn’t‣ Sinatra is not -another MV* framework -a full framework like Rails -an ORM -a game project
    7. 7. Sinatra is just a DSL written in ruby
    8. 8. Hello world
    9. 9. Hello world~$ gem install sinatra~$ vi app.rb
    10. 10. Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end
    11. 11. Hello world~$ gem install sinatra~$ vi app.rbrequire sinatraget / do hello world!end~$ ruby app.rb
    12. 12. Is it really so easy?‣ Yep! (special thanks to Ruby sweeties) - get is a just a method (more later) - the route is the parameter - the block is what should be executed - the block returns the result - the server is built in (based on Rack)
    13. 13. Let’s go RESTWhat? Yet another REST introduction?
    14. 14. 5 REST principles‣ Uniform Interface ‣ HATEAOS‣ Stateless‣ Cacheable‣ Client-Server‣ Layered System
    15. 15. Sinatra and REST‣ Sinatra supports - All HTTP verbs - Caching - Content types - Routes - ....and all you need to build a rest server
    16. 16. Give a look at the
    17. 17. Verbs‣ Support for all verbs - Get, Post, Put, Delete, Head, Options, Patch‣ They are just methods
    18. 18. Routing‣ No need of route files or route maps‣ The verb method takes the route as parameter
    19. 19. Routingget ( ‘/todos’ ) {...}get ( ‘/todo/:id’ ) {...}get ( ‘/*’ ) {...}
    20. 20. Routing Conditionsget /foo, :agent => /Mozilla/(d.d)sw?/ do "Youre using Mozilla version#{params[:agent][0]}"endget /foo do # Matches non-Mozilla browsersend
    21. 21. Routing Customset(:prob) { |v| condition { rand <= v } }get /win_a_car, :prob => 0.1 do "You won!"endget /win_a_car {"Sorry, you lost."}
    22. 22. Xml or Json‣ You can set the content_type to whatever you needcontent_type :jsoncontent_type :xml
    23. 23. Status codes‣ Set the HTTP status code is status 200 status 403
    24. 24. Http Headers‣ You can add your own headersheaders "X-My-Value" => "this is myheader"
    25. 25. Redirectredirect to ‘/todos’
    26. 26. Cache‣ You can set your cache information using the headers methodheaders "Cache-Control" => "public,must-revalidate, max-age=3600","Expires" => Time.at(Time.now.to_i + (60
    27. 27. Cache‣ Or better, you can use the expiresexpires 3600, :public
    28. 28. Filtersbefore do #...endafter do #...
    29. 29. Authentication‣ Basic authentication support through Rack‣ Key-based authentication
    30. 30. Basic Authenticationuse Rack::Auth::Basic, "Private area" do|usr, pwd| [usr, pwd] == [admin, admin]end
    31. 31. Token authenticationbefore do if env[‘HTTP_MY_KEY’] ==’rubyrocks‘ error 401 endend
    32. 32. Demo
    33. 33. Stream‣ Supports streamed content‣ Streamed responses have no Content- Length header‣ But have Transfer-Encoding: chunked
    34. 34. Inside
    35. 35. Inside‣ Sinatra source code is on github: http://github.com/sinatra/sinatra‣ Less than 2k lines of code‣ Based on Rack
    36. 36. Application styleClassic application vsModular application
    37. 37. Classic App Single file Standalone
    38. 38. Modular Apps Multi fileSubclassing Sinatra::Base Distributed as library
    39. 39. The codeWhat happen when a request arrives?get (‘/hello’) do { ‘hello world’ }
    40. 40. Where do get come from?require "sinatra"outer_self = selfget / do "outer self: #{outer_self}, inner self: #{self}"end outer self: main, inner self: #<Sinatra::Application: closures in ruby are “scope gate”
    41. 41. $ irb
    42. 42. $ irbruby-1.9.2-p180 > require sinatra
    43. 43. $ irbruby-1.9.2-p180 > require sinatra=> true
    44. 44. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)
    45. 45. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>
    46. 46. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)
    47. 47. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]
    48. 48. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target
    49. 49. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Application
    50. 50. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Applicationruby-1.9.2-p180 > Sinatra::Application.method(:get)
    51. 51. $ irbruby-1.9.2-p180 > require sinatra=> trueruby-1.9.2-p180 > method(:get)=> #<Method: Object(Sinatra::Delegator)#get>ruby-1.9.2-p180 > Sinatra::Delegator.methods(false)=> [:delegate, :target, :target=]ruby-1.9.2-p180 > Sinatra::Delegator.target=> Sinatra::Applicationruby-1.9.2-p180 > Sinatra::Application.method(:get)=> #<Method:Sinatra::Application(Sinatra::Base).get>
    52. 52. Where do get come from?‣ get is defined twice: – Once in Sinatra::Delegator a mixin extending Object – Once in Sinatra::Application‣ The Delegator implementation simply delegate to Application‣ That’s why we have get/post/... methods on main
    53. 53. How the block is invoked?‣ The route! method finds the correct routedef route_eval throw :halt, yieldend‣ throw is used to go back to the invoker
    54. 54. In base.rb‣ The invokerdef invoke res = catch(:halt) { yield } # .... other code...end
    55. 55. It’s a kind of magic!
    56. 56. Sinatra has ended his set (crowd applauds)
    57. 57. Questions?
    58. 58. demos at:http://github.com/emadb/ webnetconf_demo
    59. 59. Please rate this sessionScan the code, go online, rate this session

    ×