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 Slide

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

    View Slide

  3. Designing
    Building
    Testing
    Dienstag, 16. Oktober 12

    View Slide

  4. Assumptions
    Dienstag, 16. Oktober 12

    View Slide

  5. JSON
    Dienstag, 16. Oktober 12

    View Slide

  6. !XML
    Dienstag, 16. Oktober 12

    View Slide

  7. Designing
    Dienstag, 16. Oktober 12

    View Slide

  8. REST
    Dienstag, 16. Oktober 12

    View Slide

  9. REpresenational State Transfer
    Dienstag, 16. Oktober 12

    View Slide

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

    View 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 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 Slide

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

    View Slide

  14. HATEOAS
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  16. Hypermedia
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  20. REST
    Dienstag, 16. Oktober 12

    View Slide

  21. Benefits of
    Hypermedia
    Dienstag, 16. Oktober 12

    View Slide

  22. API Versioning
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  26. Code Duplication
    Dienstag, 16. Oktober 12

    View Slide

  27. Legacy Code
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

  30. Reasons for
    versioning
    Dienstag, 16. Oktober 12

    View Slide

  31. Data structure
    changes
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  33. Different auth
    mechanism
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  35. URL changes
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  37. Expose one
    endpoint
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  39. Real World
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

  42. Aggregations
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  44. Suggestion
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  48. Authentication
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

  51. Session-Based
    Dienstag, 16. Oktober 12

    View Slide

  52. External?
    Dienstag, 16. Oktober 12

    View Slide

  53. User based?
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  55. OAuth2
    Dienstag, 16. Oktober 12

    View Slide

  56. Dienstag, 16. Oktober 12

    View Slide

  57. SSL!
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  59. Auth inception
    Dienstag, 16. Oktober 12

    View Slide

  60. App based?
    Dienstag, 16. Oktober 12

    View Slide

  61. API_KEY
    API_SECRET
    Dienstag, 16. Oktober 12

    View Slide

  62. Using authlogic?
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  64. Building
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View 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 Slide

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

    View 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 Slide

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

    View 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 Slide

  72. Customize output
    Dienstag, 16. Oktober 12

    View 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 Slide

  74. Dienstag, 16. Oktober 12

    View Slide

  75. jBuilder
    Dienstag, 16. Oktober 12

    View Slide

  76. Dienstag, 16. Oktober 12

    View Slide

  77. Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  83. Associations
    Dienstag, 16. Oktober 12

    View 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 Slide

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

    View 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 Slide

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

    View Slide

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

    View Slide

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

    View Slide

  90. ActiveModel
    serializers
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  99. Associations
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  101. (CommentSerializer)
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  103. RABL
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

  106. Associations
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  110. ROAR
    Dienstag, 16. Oktober 12

    View Slide

  111. Almost like
    serializers
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  113. HAL
    implementation
    Dienstag, 16. Oktober 12

    View Slide

  114. No examples
    Dienstag, 16. Oktober 12

    View Slide

  115. Testing
    Dienstag, 16. Oktober 12

    View Slide

  116. Assumption
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  121. Rails
    Dienstag, 16. Oktober 12

    View 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 Slide

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

    View 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 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 Slide

  126. Why?
    Dienstag, 16. Oktober 12

    View Slide

  127. Capybara?
    Dienstag, 16. Oktober 12

    View Slide

  128. Cucumber?
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  130. Response Codes
    Dienstag, 16. Oktober 12

    View Slide

  131. Valid JSON
    Dienstag, 16. Oktober 12

    View Slide

  132. JSON structure
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

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

    View Slide

  135. Workflows
    Dienstag, 16. Oktober 12

    View Slide

  136. Interactions
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  138. External Client
    Dienstag, 16. Oktober 12

    View Slide

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

    View Slide

  140. Test script
    Dienstag, 16. Oktober 12

    View 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 Slide

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

    View Slide

  143. Q & A
    Dienstag, 16. Oktober 12

    View 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 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 Slide