Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JSON - Schmason

JSON - Schmason

Using Rails for building Web APIs

Jan Krutisch

October 16, 2012
Tweet

More Decks by Jan Krutisch

Other Decks in Technology

Transcript

  1. JSON - Schmason
    Using Rails for building Web APIs
    WebTech Conference 2012
    Jan Krutisch
    http://jan.krutisch.de/
    Dienstag, 16. Oktober 12

    View full-size slide

  2. JSON - Schmason
    Using Rails for building Web APIs
    WebTech Conference 2012
    Jan Krutisch
    http://jan.krutisch.de/
    Dienstag, 16. Oktober 12

    View full-size slide

  3. Designing
    Building
    Testing
    Dienstag, 16. Oktober 12

    View full-size slide

  4. Assumptions
    Dienstag, 16. Oktober 12

    View full-size slide

  5. JSON
    Dienstag, 16. Oktober 12

    View full-size slide

  6. !XML
    Dienstag, 16. Oktober 12

    View full-size slide

  7. Designing
    Dienstag, 16. Oktober 12

    View full-size slide

  8. REST
    Dienstag, 16. Oktober 12

    View full-size slide

  9. REpresenational State Transfer
    Dienstag, 16. Oktober 12

    View full-size slide

  10. „Pragmatic REST“
    Dienstag, 16. Oktober 12

    View full-size slide

  11. POST /books.json
    GET /books.json
    GET /books/1.json
    PUT /books/1.json
    DELETE /books/1.json
    Dienstag, 16. Oktober 12

    View full-size slide

  12. POST /books/1/comments.json
    GET /books/1/comments.json
    GET /books/1/comments/1.json
    PUT /books/1/comments/1.json
    DELETE /books/1/comments/1.json
    Dienstag, 16. Oktober 12

    View full-size slide

  13. Hypermedia As The
    Engine Of Application
    State
    Dienstag, 16. Oktober 12

    View full-size slide

  14. HATEOAS
    Dienstag, 16. Oktober 12

    View full-size slide

  15. Hype As The Engine
    Of Acronym Silliness
    Dienstag, 16. Oktober 12

    View full-size slide

  16. Hypermedia
    Dienstag, 16. Oktober 12

    View full-size slide

  17. GET /books.json
    GET /books/1.json
    Dienstag, 16. Oktober 12

    View full-size slide

  18. [...]
    "_links": {
    ! "self": {"href":"/books/1.json"},
    ! "comments":{"href":"/books/1/comments.json"}
    }
    [...]
    Dienstag, 16. Oktober 12

    View full-size slide

  19. Hypermedia As The
    Engine Of Application
    State
    Dienstag, 16. Oktober 12

    View full-size slide

  20. REST
    Dienstag, 16. Oktober 12

    View full-size slide

  21. Benefits of
    Hypermedia
    Dienstag, 16. Oktober 12

    View full-size slide

  22. API Versioning
    Dienstag, 16. Oktober 12

    View full-size slide

  23. foo.com/api/v1/
    Dienstag, 16. Oktober 12

    View full-size slide

  24. Don't do it!
    Dienstag, 16. Oktober 12

    View full-size slide

  25. Try to avoid it
    Dienstag, 16. Oktober 12

    View full-size slide

  26. Code Duplication
    Dienstag, 16. Oktober 12

    View full-size slide

  27. Legacy Code
    Dienstag, 16. Oktober 12

    View full-size slide

  28. if request.version < 2
    fffffffffuuuuuuuuu!
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  29. if request.version < 2
    fffffffffuuuuuuuuu!
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  30. Reasons for
    versioning
    Dienstag, 16. Oktober 12

    View full-size slide

  31. Data structure
    changes
    Dienstag, 16. Oktober 12

    View full-size slide

  32. additions: good
    subtractions: bad
    Dienstag, 16. Oktober 12

    View full-size slide

  33. Different auth
    mechanism
    Dienstag, 16. Oktober 12

    View full-size slide

  34. Support both...
    Dienstag, 16. Oktober 12

    View full-size slide

  35. URL changes
    Dienstag, 16. Oktober 12

    View full-size slide

  36. A-Ha!
    Dienstag, 16. Oktober 12

    View full-size slide

  37. Expose one
    endpoint
    Dienstag, 16. Oktober 12

    View full-size slide

  38. Use Hypermedia to
    reference other urls
    Dienstag, 16. Oktober 12

    View full-size slide

  39. Real World
    Dienstag, 16. Oktober 12

    View full-size slide

  40. API
    iPhone App
    Android App
    Mobile Web
    Desktop App
    Mashups
    Dienstag, 16. Oktober 12

    View full-size slide

  41. Shitty connections,
    expensive data
    plans, low memory
    Dienstag, 16. Oktober 12

    View full-size slide

  42. Aggregations
    Dienstag, 16. Oktober 12

    View full-size slide

  43. Optimisations for
    different clients
    Dienstag, 16. Oktober 12

    View full-size slide

  44. Suggestion
    Dienstag, 16. Oktober 12

    View full-size slide

  45. Have a "REST" api
    Dienstag, 16. Oktober 12

    View full-size slide

  46. http://stateless.co/hal_specification.html
    Dienstag, 16. Oktober 12

    View full-size slide

  47. Build APIs on top of
    APIs
    Dienstag, 16. Oktober 12

    View full-size slide

  48. Authentication
    Dienstag, 16. Oktober 12

    View full-size slide

  49. Internal/ External?
    Dienstag, 16. Oktober 12

    View full-size slide

  50. Javascript-App?
    Dienstag, 16. Oktober 12

    View full-size slide

  51. Session-Based
    Dienstag, 16. Oktober 12

    View full-size slide

  52. External?
    Dienstag, 16. Oktober 12

    View full-size slide

  53. User based?
    Dienstag, 16. Oktober 12

    View full-size slide

  54. SSL+Basic Auth
    Dienstag, 16. Oktober 12

    View full-size slide

  55. OAuth2
    Dienstag, 16. Oktober 12

    View full-size slide

  56. Dienstag, 16. Oktober 12

    View full-size slide

  57. SSL!
    Dienstag, 16. Oktober 12

    View full-size slide

  58. http://github.com/songkick/oauth2-provider
    Dienstag, 16. Oktober 12

    View full-size slide

  59. Auth inception
    Dienstag, 16. Oktober 12

    View full-size slide

  60. App based?
    Dienstag, 16. Oktober 12

    View full-size slide

  61. API_KEY
    API_SECRET
    Dienstag, 16. Oktober 12

    View full-size slide

  62. Using authlogic?
    Dienstag, 16. Oktober 12

    View full-size slide

  63. http://github.com/phurni/authlogic_api
    Dienstag, 16. Oktober 12

    View full-size slide

  64. Building
    Dienstag, 16. Oktober 12

    View full-size slide

  65. https://github.com/halfbyte/bookrack/
    Dienstag, 16. Oktober 12

    View full-size slide

  66. ✓ Build an API
    Dienstag, 16. Oktober 12

    View full-size slide

  67. POST /books.json
    GET /books.json
    GET /books/1.json
    PUT /books/1.json
    DELETE /books/1.json
    Dienstag, 16. Oktober 12

    View full-size slide

  68. $ rails g scaffold Book ...
    Dienstag, 16. Oktober 12

    View full-size slide

  69. def index
    @books = Book.all
    respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @books }
    end
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  70. respond_to :html, :json
    def index
    @books = Book.all
    respond_with @books
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  71. [
    {
    "author": "Jan Krutisch",
    "created_at": "2012-10-14T16:29:17Z",
    "description": "A funny story",
    "id": 1,
    "isbn": "",
    "title": "The Website is Down",
    "updated_at": "2012-10-14T16:29:17Z"
    }
    ]
    Dienstag, 16. Oktober 12

    View full-size slide

  72. Customize output
    Dienstag, 16. Oktober 12

    View full-size slide

  73. def index
    @books = Book.all
    respond_with @books.map{|b| {
    id: b.id,
    title: b.title,
    author: b.author,
    created_at: b.created_at
    }}
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  74. Dienstag, 16. Oktober 12

    View full-size slide

  75. jBuilder
    Dienstag, 16. Oktober 12

    View full-size slide

  76. Dienstag, 16. Oktober 12

    View full-size slide

  77. Dienstag, 16. Oktober 12

    View full-size slide

  78. gem "jbuilder"
    Dienstag, 16. Oktober 12

    View full-size slide

  79. books.json.jbuilder
    Dienstag, 16. Oktober 12

    View full-size slide

  80. # index.json.jbuilder
    json.(@books) do |json, book|
    json.partial! book
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  81. _book.json.jbuilder
    Dienstag, 16. Oktober 12

    View full-size slide

  82. # _book.json.jbuilder
    json.(book, :id, :title, :author)
    Dienstag, 16. Oktober 12

    View full-size slide

  83. Associations
    Dienstag, 16. Oktober 12

    View full-size slide

  84. # _book.json.jbuilder
    json.(book, :id, :title, :author)
    json.comments(book.comments) do |json, comment|
    json.partial! comment
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  85. # comments/_comment.json.jbuilder
    json.(comment, :text, :name)
    Dienstag, 16. Oktober 12

    View full-size slide

  86. [
    {
    "book": {
    "id": 1,
    "title": "The Website is down",
    "author": "Jan Krutisch",
    "comments": [
    {
    "text": "A shitty comment",
    "name": "Jan"
    },
    {
    "text": "Another shitty comment",
    "name": "Felix Baumgartner"
    },
    {
    "text": "I disagree!",
    "name": "Troll"
    }
    ]
    }
    }
    ]
    Dienstag, 16. Oktober 12

    View full-size slide

  87. + Kind of the right place
    + Full view infrastructure available
    + Easy to use
    Dienstag, 16. Oktober 12

    View full-size slide

  88. I hated .builder
    Dienstag, 16. Oktober 12

    View full-size slide

  89. Data structures
    vs.
    Content representation
    Dienstag, 16. Oktober 12

    View full-size slide

  90. ActiveModel
    serializers
    Dienstag, 16. Oktober 12

    View full-size slide

  91. gem "active_model_serializers"
    Dienstag, 16. Oktober 12

    View full-size slide

  92. gem "active_model_serializers"
    Dienstag, 16. Oktober 12

    View full-size slide

  93. gem "active_model_serializers",
    :git => "git://github.com/josevalim/active_model_serializers.git"
    Dienstag, 16. Oktober 12

    View full-size slide

  94. serializers/
    book_serializer.rb
    Dienstag, 16. Oktober 12

    View full-size slide

  95. class BookSerializer < ActiveModel::Serializer
    attributes :id, :author, :title
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  96. {
    "books": [
    {
    "id": 1,
    "author": "Jan Krutisch",
    "title": "The Website is Down"
    }
    ]
    }
    Dienstag, 16. Oktober 12

    View full-size slide

  97. ActiveModel::ArraySerializer.root = false
    Dienstag, 16. Oktober 12

    View full-size slide

  98. [
    {
    "id": 1,
    "author": "Jan Krutisch",
    "title": "The Website is Down"
    }
    ]
    Dienstag, 16. Oktober 12

    View full-size slide

  99. Associations
    Dienstag, 16. Oktober 12

    View full-size slide

  100. class BookSerializer < ActiveModel::Serializer
    attributes :id, :author, :title
    has_many :comments
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  101. (CommentSerializer)
    Dienstag, 16. Oktober 12

    View full-size slide

  102. + mostly declarative, with fallbacks
    + no view code to mangle data structures
    - no helpers except URL helpers
    Dienstag, 16. Oktober 12

    View full-size slide

  103. RABL
    Dienstag, 16. Oktober 12

    View full-size slide

  104. gem "rabl"
    Dienstag, 16. Oktober 12

    View full-size slide

  105. # books/index.json.rabl
    collection @books
    attributes :id, :title, :author
    Dienstag, 16. Oktober 12

    View full-size slide

  106. Associations
    Dienstag, 16. Oktober 12

    View full-size slide

  107. # books/index.json.rabl
    collection @books
    attributes :id, :title, :author
    child :comments do
    attributes :text, :name
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  108. embed? glue? wat?
    Dienstag, 16. Oktober 12

    View full-size slide

  109. + Mosty declarative
    + Full view infrastructure
    - Kinda ugly, kinda weird
    - (It get's weirder the more you look)
    Dienstag, 16. Oktober 12

    View full-size slide

  110. ROAR
    Dienstag, 16. Oktober 12

    View full-size slide

  111. Almost like
    serializers
    Dienstag, 16. Oktober 12

    View full-size slide

  112. Both Serializing and
    Deserializing
    Dienstag, 16. Oktober 12

    View full-size slide

  113. HAL
    implementation
    Dienstag, 16. Oktober 12

    View full-size slide

  114. No examples
    Dienstag, 16. Oktober 12

    View full-size slide

  115. Testing
    Dienstag, 16. Oktober 12

    View full-size slide

  116. Assumption
    Dienstag, 16. Oktober 12

    View full-size slide

  117. Test::Unit
    Dienstag, 16. Oktober 12

    View full-size slide

  118. 1. Unit testing
    Dienstag, 16. Oktober 12

    View full-size slide

  119. It's understood
    Dienstag, 16. Oktober 12

    View full-size slide

  120. 2. Integration
    testing
    Dienstag, 16. Oktober 12

    View full-size slide

  121. Rails
    Dienstag, 16. Oktober 12

    View full-size slide

  122. require 'test_helper'
    require 'json'
    class BooksTest < ActionDispatch::IntegrationTest
    test "books.json should return valid json" do
    get "/books.json"
    body = JSON.parse(response.body)
    assert_not_nil body
    assert_equal 200, status
    end
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  123. Rack::Test
    Dienstag, 16. Oktober 12

    View full-size slide

  124. require 'test_helper'
    require 'json'
    class BooksRackTest < ActiveSupport::TestCase
    include Rack::Test::Methods
    def app; Rails.application; end
    test "should return valid json" do
    get '/books.json'
    assert last_response.ok?
    body = JSON.parse(last_response.body)
    assert_not_nil body
    end
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  125. require 'test_helper'
    require 'json'
    class BooksRackTest < ActiveSupport::TestCase
    include Rack::Test::Methods
    def app; Rails.application; end
    test "should return valid json" do
    get '/books.json'
    assert last_response.ok?
    body = JSON.parse(last_response.body)
    assert_not_nil body
    end
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  126. Why?
    Dienstag, 16. Oktober 12

    View full-size slide

  127. Capybara?
    Dienstag, 16. Oktober 12

    View full-size slide

  128. Cucumber?
    Dienstag, 16. Oktober 12

    View full-size slide

  129. What to test?
    Dienstag, 16. Oktober 12

    View full-size slide

  130. Response Codes
    Dienstag, 16. Oktober 12

    View full-size slide

  131. Valid JSON
    Dienstag, 16. Oktober 12

    View full-size slide

  132. JSON structure
    Dienstag, 16. Oktober 12

    View full-size slide

  133. (keep it simple)
    Dienstag, 16. Oktober 12

    View full-size slide

  134. ETags, Cache
    Headers
    Dienstag, 16. Oktober 12

    View full-size slide

  135. Workflows
    Dienstag, 16. Oktober 12

    View full-size slide

  136. Interactions
    Dienstag, 16. Oktober 12

    View full-size slide

  137. 3. External testing
    Dienstag, 16. Oktober 12

    View full-size slide

  138. External Client
    Dienstag, 16. Oktober 12

    View full-size slide

  139. (Client Lib?)
    Dienstag, 16. Oktober 12

    View full-size slide

  140. Test script
    Dienstag, 16. Oktober 12

    View full-size slide

  141. namespace :api_tests do
    desc "Testing the /books endpoint"
    task :books do
    require 'rest_client'
    require 'json'
    json = JSON.parse(
    RestClient.get('http://localhost:3000/books.json')
    )
    exit(1) if (json.nil?)
    end
    end
    Dienstag, 16. Oktober 12

    View full-size slide

  142. Testing
    >>>
    Monitoring
    Dienstag, 16. Oktober 12

    View full-size slide

  143. Q & A
    Dienstag, 16. Oktober 12

    View full-size slide

  144. Thanks!
    • http://jan.krutisch.de/
    • http://twitter.com/halfbyte
    • https://alpha.app.net/halfbyte
    • https://github.com/halfbyte
    • http://thesinglepageapp.com
    Dienstag, 16. Oktober 12

    View full-size slide

  145. Thanks!
    • http://jan.krutisch.de/
    • http://twitter.com/halfbyte
    • https://alpha.app.net/halfbyte
    • https://github.com/halfbyte
    • http://thesinglepageapp.com (shameless plug)
    Dienstag, 16. Oktober 12

    View full-size slide