Slide 1

Slide 1 text

metrics.watch | freeGoogleAnalyticsCourse.com Build APIs with Ruby, on or off Rails Jean-Philippe Boily @jipiboily | jipiboily.com Founder of Metrics Watch http://metrics.watch

Slide 2

Slide 2 text

metrics.watch | freeGoogleAnalyticsCourse.com whoami Jean-Philippe “JP” Boily Founder of Metrics Watch SaaS consultant Software Engineer with experience working remotely for US- based SaaS startups Last one was Rainforest QA (YC backed)

Slide 3

Slide 3 text

metrics.watch | freeGoogleAnalyticsCourse.com Metrics Watch Alerts for Google Analytics in near real-time. Support for custom metrics, filters, alert templates, etc. Check us out! http://metrics.watch PS: I have stickers!

Slide 4

Slide 4 text

metrics.watch | freeGoogleAnalyticsCourse.com Let’s talk about APIs!

Slide 5

Slide 5 text

Assumptions

Slide 6

Slide 6 text

metrics.watch | freeGoogleAnalyticsCourse.com I am assuming that you know… … how web works … how routing works in general … how to query data and present it in some ways (i.e., HTML, JSON or XML) … some Ruby

Slide 7

Slide 7 text

Frameworks & libraries

Slide 8

Slide 8 text

metrics.watch | freeGoogleAnalyticsCourse.com Rack Rack: a Ruby Webserver Interface. Super basic, probably avoid to use directly. # my_rack_app.rb require 'rack' app = Proc.new do |env| ['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']] end Rack::Handler::WEBrick.run app

Slide 9

Slide 9 text

metrics.watch | freeGoogleAnalyticsCourse.com Sinatra Not a framework, a library. Light, very light. You want more? Add it yourself! require 'sinatra' get '/hi' do { hello: 'world' } end

Slide 10

Slide 10 text

metrics.watch | freeGoogleAnalyticsCourse.com Grape “micro-framework” for APIs It’s a DSL. Validation, versioning and more built-in. You want more? Add it yourself!

Slide 11

Slide 11 text

module Twitter class API < Grape::API version 'v1', using: :header, vendor: 'twitter' format :json prefix :api helpers do def current_user @current_user ||= User.authorize!(env) end def authenticate! error!('401 Unauthorized', 401) unless current_user end end resource :statuses do desc 'Return a public timeline.' get :public_timeline do Status.limit(20) end desc 'Create a status.' params do requires :status, type: String, desc: 'Your status.' end post do authenticate! Status.create!({ user: current_user, text: params[:status] }) end end end end

Slide 12

Slide 12 text

metrics.watch | freeGoogleAnalyticsCourse.com Grape Can easily get messy for complex APIs Testing issues because, DSL

Slide 13

Slide 13 text

metrics.watch | freeGoogleAnalyticsCourse.com Hanami (formerly Lotus.rb) Plain Ruby modular web framework Seems to have a very nice architecture approach. http://lucaguidi.com/2015/11/24/json-api-apps-with-lotus.html http://lucaguidi.com/2015/12/09/25000-requests-per-second-for-rack-json-api-with-mruby.html

Slide 14

Slide 14 text

metrics.watch | freeGoogleAnalyticsCourse.com Hanami # controllers/books.rb module Bookshelf::API::Controllers::Books class Index include Lotus::Action def call(params) end end end # config/routes.rb: get '/books', to: 'books#index'

Slide 15

Slide 15 text

metrics.watch | freeGoogleAnalyticsCourse.com Rails Full featured framework with everything you might need. It just works™. Best in breed monolith builder!

Slide 16

Slide 16 text

metrics.watch | freeGoogleAnalyticsCourse.com rails-api $ rails new my_api_project --api Available as a gem for a couple years, now merged in Rails 5 (beta):

Slide 17

Slide 17 text

metrics.watch | freeGoogleAnalyticsCourse.com Sinatra and Grape…in Rails? FYI, you can mount any Rack-based app in Rails to benefit of some of the Rails features

Slide 18

Slide 18 text

What should I use?

Slide 19

Slide 19 text

metrics.watch | freeGoogleAnalyticsCourse.com Rails, just Rails You have a Rails app already? Use it.
 You don’t have a Ruby app at all? Start with Rails API (if you know you won’t be serving any HTML pages)

Slide 20

Slide 20 text

metrics.watch | freeGoogleAnalyticsCourse.com Why? •It just works. Almost nothing to configure. •Reload in development easily. •Easy deployment. •Conventions makes it easy to onboard people. •Takes care of many security concerns for you.

Slide 21

Slide 21 text

metrics.watch | freeGoogleAnalyticsCourse.com etc…

Slide 22

Slide 22 text

Building a Rails API

Slide 23

Slide 23 text

metrics.watch | freeGoogleAnalyticsCourse.com Routing (& versionning) # config/routes.rb Rails.application.routes.draw do namespace :api do # /api namespace :v1 do # /api/v1 get 'metrics_providers', to: 'metrics_providers#index' # /api/v1/alerts resources :watchers, path: 'alerts' end end end

Slide 24

Slide 24 text

metrics.watch | freeGoogleAnalyticsCourse.com Routing maps to…

Slide 25

Slide 25 text

metrics.watch | freeGoogleAnalyticsCourse.com Controllers class Api::V1::MetricsProvidersController < ApplicationController def index providers = current_account.metrics_providers render json: providers end end This is not going to be nice, by default!

Slide 26

Slide 26 text

We have an API!

Slide 27

Slide 27 text

but wait…

Slide 28

Slide 28 text

metrics.watch | freeGoogleAnalyticsCourse.com Serializing JSON class Api::V1::MetricsProvidersController < ApplicationController def index providers = current_account.metrics_providers render json: providers end end

Slide 29

Slide 29 text

metrics.watch | freeGoogleAnalyticsCourse.com Serializing: your options •ActiveModel::Serializer •Jbuilder (not the IDE!) •brainstem •build your own

Slide 30

Slide 30 text

metrics.watch | freeGoogleAnalyticsCourse.com ActiveModel::Serializer Part of the initial Rails API initiative. Not a DSL, just Ruby. No setup. Weird state right now. https://github.com/rails-api/active_model_serializers

Slide 31

Slide 31 text

metrics.watch | freeGoogleAnalyticsCourse.com ActiveModel::Serializer class WatcherSerializer < ActiveModel::Serializer attributes :id, :name, :metric_name, :threshold, :interval_type, :email_recipients attribute :watcher_type, key: :comparison_type def email_recipients object.destination_emails.map {|de| de.settings['email'] } end end

Slide 32

Slide 32 text

metrics.watch | freeGoogleAnalyticsCourse.com ActiveModel::Serializer { "data": { "id": "150", "type": "watchers", "attributes": { "name": "Traffic Spike (near real-time)", "metric_name": "ga:sessions", "threshold": 250, "interval_type": "today", "google_analytics_profile_id": "123", "metrics_provider_id": 30, "email_recipients": [ "[email protected]" ], "google_analytics_filters": null, "comparison_type": "goes_above" } } }

Slide 33

Slide 33 text

metrics.watch | freeGoogleAnalyticsCourse.com Jbuilder Has the worst name. In Rails Gemfiles by default. I don’t like it…but it works.

Slide 34

Slide 34 text

metrics.watch | freeGoogleAnalyticsCourse.com Jbuilder # app/views/message/show.json.jbuilder json.content format_content(@message.content) json.(@message, :created_at, :updated_at) json.author do json.name @message.creator.name.familiar json.url url_for(@message.creator, format: :json) end if current_user.admin? json.visitors calculate_visitors(@message) end json.comments @message.comments, :content, :created_at json.attachments @message.attachments do |attachment| json.filename attachment.filename json.url url_for(attachment) end

Slide 35

Slide 35 text

metrics.watch | freeGoogleAnalyticsCourse.com brainstem Never used it and seems massively overkill for 90%+ of the use cases. (not half of the example fits in this screen) https://github.com/mavenlink/brainstem

Slide 36

Slide 36 text

metrics.watch | freeGoogleAnalyticsCourse.com Build your own serializers It’s just Ruby generating a hash. Model#as_json

Slide 37

Slide 37 text

metrics.watch | freeGoogleAnalyticsCourse.com Build your own serializers class Watcher < ActiveRecord::Base def as_json { id: id, name: name, metric_name: metric_name, threshold: threshold, interval_type: interval_type } end end

Slide 38

Slide 38 text

metrics.watch | freeGoogleAnalyticsCourse.com Watch out for… •pagination •relations •N+1 queries

Slide 39

Slide 39 text

Authentication

Slide 40

Slide 40 text

metrics.watch | freeGoogleAnalyticsCourse.com It’s complicated™

Slide 41

Slide 41 text

metrics.watch | freeGoogleAnalyticsCourse.com KISS Internal only, for connected users to the Rails app? Just use what’s there (i.e., Devise, …) For external APIs just create one API key per account or user (to start with)

Slide 42

Slide 42 text

metrics.watch | freeGoogleAnalyticsCourse.com Too simple? Use OAuth. Look at Doorkeeper and rack-oauth2

Slide 43

Slide 43 text

Validation & errors

Slide 44

Slide 44 text

metrics.watch | freeGoogleAnalyticsCourse.com It’s complicated™

Slide 45

Slide 45 text

metrics.watch | freeGoogleAnalyticsCourse.com KISS Grape offer API level basic validation (presence) Rails doesn’t. Easy to add.

Slide 46

Slide 46 text

metrics.watch | freeGoogleAnalyticsCourse.com Model validations? Yes! Translate that into a JSON friendly format and you’re done. Just be consistent with your format.

Slide 47

Slide 47 text

metrics.watch | freeGoogleAnalyticsCourse.com Status codes 200? 201? 202? 401? Semantic usage, please! https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Slide 48

Slide 48 text

Testing

Slide 49

Slide 49 text

metrics.watch | freeGoogleAnalyticsCourse.com Should you write tests for the API?

Slide 50

Slide 50 text

metrics.watch | freeGoogleAnalyticsCourse.com YES, PLEASE!!!

Slide 51

Slide 51 text

metrics.watch | freeGoogleAnalyticsCourse.com Tomorrow… I’m talking about testing in Ruby, same time, in a different room.

Slide 52

Slide 52 text

metrics.watch | freeGoogleAnalyticsCourse.com What to test? Authentication Output format Core logic with different contexts Service objets? Just make sure it’s called!

Slide 53

Slide 53 text

Documentation

Slide 54

Slide 54 text

metrics.watch | freeGoogleAnalyticsCourse.com Internal or external? Internal? Not too much doc, if any.

Slide 55

Slide 55 text

metrics.watch | freeGoogleAnalyticsCourse.com Swagger + Grape https://github.com/ruby-grape/grape-swagger Interactive documentation

Slide 56

Slide 56 text

metrics.watch | freeGoogleAnalyticsCourse.com Apiary “Powerful API Design Stack. Built for Developers.”

Slide 57

Slide 57 text

metrics.watch | freeGoogleAnalyticsCourse.com Apiary Create, design, mock & test an API in seconds Interactive doc with cURL & code generation

Slide 58

Slide 58 text

metrics.watch | freeGoogleAnalyticsCourse.com Apiary Example doc from a client: http://api.gemnasium.com/

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

metrics.watch | freeGoogleAnalyticsCourse.com Blueprint “API Blueprint. A powerful high-level API description language for web APIs.” https://apiblueprint.org/

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

metrics.watch | freeGoogleAnalyticsCourse.com SWAG!!! Thanks Apiary!!!

Slide 63

Slide 63 text

I did not talk about…

Slide 64

Slide 64 text

metrics.watch | freeGoogleAnalyticsCourse.com I did not talk about… • JSON API - http://jsonapi.org/ • http://json-schema.org/ • Hypermedia API • Caching …but read about those!

Slide 65

Slide 65 text

Conclusion?

Slide 66

Slide 66 text

metrics.watch | freeGoogleAnalyticsCourse.com Key takeaways •Use tools that exists, works well and have a long track record of success •Use Rails •KISS

Slide 67

Slide 67 text

GET AWESOME GIFTS freeGAcourse.com • free course “How to get the most out of Google Analytics” • longer trial for Metrics Watch (1 month instead of 14 days) ConFooLove.com • Slides for my two talks at ConFoo • testing toolbox cheatsheet • API toolbox cheatsheet • early invite to join my free email course about distributed teams, for pre-launch THANKS