Building RESTful APIs w/ Grape

23,147 views

Published on

NYC.rb talk on building

Published in: Technology
  • Be the first to comment

Building RESTful APIs w/ Grape

  1. 1. Daniel Doubrovkine / Art.sydblock@dblock.org @dblockdotorg
  2. 2. Solid API or Else …http://www.youtube.com/watch?v=l9vYE7B1_PU
  3. 3. The Rails Way: M(V)Cconfig/routes.rbresources :artistsapp/controllers/artists_controller.rbclass ArtistsController < ApplicationController def index @artists = … # all kinds of stuff that serves views respond_to do |format| format.html { @artists } format.json { render json: @artists.as_json } end endEnd
  4. 4. The Rails Way: MVCapp/views/artists/index.json.erb-@artists.each do |artist| { first_name: <%= @artist.first_name.to_json %>, last_name: <%= @artist.last_name.to_json %> }
  5. 5. Occupy Rails?» Where does the API start and end?» How are we going to build API v2 on top of v1?» Is API testing the same as controller testing?» How much discipline are we going to need to keep sanity?» How will deal with more difficult problems? Caching, authentication, authorization …
  6. 6. Modern Web Applications: NoRails» MVC UI» RESTful API» Storage
  7. 7. Grape» API DSL class API < Grape::API version „1 rack-based / middleware http://github.com/intridea/grape namespace :artist get “:id” do Artist.find(params[:id]).as_json end end namespace :artists do get “/” do Artist.all.as_json end end end
  8. 8. Documentation» Developers Have the Attention Span of a Fish * * when reading documentation» Written in Markdown http://code.dblock.org/rendering-markdown-documents-in-rails» Reference will be Generated» API Sandboxes https://github.com/mmcnierney14/API-Sandbox» API Explorer https://github.com/mmcnierney14/API-Sandbox
  9. 9. Testing an API# spec/spec_helper.rbRSpec.configure do |config| config.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => { :file_path => /spec/api/ }end See “Writing Tests” @ https://github.com/intridea/grape
  10. 10. Mocking is for Java Programmersdescribe "artworks" do before(:each) do login_as Fabricate(:admin) end describe "GET /api/v1/artwork/:slug" do it "returns an unpublished artwork" do artwork = Fabricate(:artwork, published: false) get "/api/v1/artwork/#{artwork.slug}" response.status.should == 200 response.body.at_json_path(“id”).should == artwork.slug # Pathy! end end endend
  11. 11. Version 1 Births Version 2 » Include Api_v1 » Folder-Driven Development (FDD) api/api_v1/… module Api_v1 module Api_v2 version v1„ version v2„ module Api_v1_Me module Api_v1_Me module Api_v1_Artworks module Api_v2_Artworks # ... # ... end endSee “Modularizing Grape API” @ http://code.dblock.org/modularizing-a-ror-grape-api-multiple-versions
  12. 12. Exceptions Abort Flow » Don’t question yourself, raise a hand. rescue_from :all, :backtrace => true error_format :json rescue_from Mongoid::Errors::Validations do |e| rack_response({ :message => e.message, :detail => e.document.errors, :backtrace => e.backtrace }.to_json) end endSee “Grape: trapping all exceptions within the API” @ http://code.dblock.org/grape-trapping-all-exceptions-within-the-api
  13. 13. Authentication Methods» XApp: Exchange client ID for an XApp token api/v1/api_xapp_auth.rb» OAuth 2.0: Browser-Based Redirects controllers/oauth_controller.rb» XAuth: Exchange credentials for an OAuth token controllers/oauth_controller.rb» Forms Login to Website devise/warden via user.rb See “Grape: API Authentication w/ Devise” @ http://code.dblock.org/grape-api-authentication-w-devise
  14. 14. Authenticated Users» Unauthenticated Calls» Authorized Apps» Logged In Users, RBAC def authenticated_user authenticated error!(Unauthorized, 401) unless current_user end
  15. 15. Object Identity» Everything has an ID » Internal ID: BSON ObjectId » External ID: humanly-readable ID» ID is the same for all API consumers» API consumers know of a single ID » When do I use a Slug? » When do I use BSON ObjectId?
  16. 16. JSON Formats» ActiveRecord as_json passes options recursively :all – all fields visible to the object’s owner :public – all fields visible to a user with :read permissions :short – enough fields visible to a user with :read permissions, used within a collection» JSON data can be grown incrementally
  17. 17. POST and PUT» Validate Input Parameters in Models save(hashie) valid_hash_fields :first, :last
  18. 18. Authorization» Admins have :create, :read, :update, :delete on everything, also known as :manage» Partners have :manage on their partner data eg. partner location, get :all JSON» Users have :manage on their personal data eg. my collection, get :all JSON» Everyone has :read on public data eg. a published artwork, get :public JSON
  19. 19. Authorization Usage» Implemented w/ CanCan cannot :read, Artwork can :read, Artwork do |artwork| artwork.published end error!(„Unauthorized, 403) unless current_user.has_authorization_to?(:delete, artist)
  20. 20. Pagination» paginate(collection) » :offset or :page » :size Pagination Helper for Grape @ https://gist.github.com/1335242
  21. 21. Logging» Implemented as Rack Middleware» Logs API Calls
  22. 22. Caching» Implemented w/Rails Cache / Memcached» Key based on Class and Identity » Cache Locally » Invalidate Aggressively
  23. 23. Cache Busting» IE9 See “IE9: Cache-Busting with Grape Middleware” @ http://code.dblock.org/ie9-cache-busting-with-grape-middleware
  24. 24. Instrumentation» See API Stats in New Relic config/initializers/new_relic_agent_instrumentation_api.rb See “New Relic: Performance Instrumentaiton w/ Grape” @ http://code.dblock.org/new-relic-performance-instrumentation-with-grape-api
  25. 25. Performance» Trends
  26. 26. Next» Deep Data» Caching in JSON» Generated Documentation
  27. 27. How to design a good API and why it matters (Joshua Bloch)http://www.youtube.com/watch?v=aAb7hSCtvGw1. Do one thing well2. API is a Language, names matter3. Documentation matters4. Minimize mutability5. Don’t make the client do anything the API could do

×