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

Building APIs on Rails 5 with AMS

Building APIs on Rails 5 with AMS

A lot of people have being using Rails to develop both their internal or external API, but building a high quality API can be hard, and performance is a key point to achieve it.
I'll share my stories with APIs, and tell you how Active Model Serializer, component of Rails-API, helped me. AMS have being used across thousands of applications bringing convention over configuration to JSON generation.
This talk will give you a sneak peek of a new version of AMS that we have being working on, it's new cache conventions, and how it's being considered to be shipped by default in new Rails 5.

João Moura

April 22, 2015
Tweet

More Decks by João Moura

Other Decks in Programming

Transcript

  1. API

  2. An API should do one thing, and do it well.

    “ Joshua Blonch, Google tech talk, Jan 2007
  3. rails-api Subset of a normal Rails application, created for applications

    that don't require all functionality of a complete Rails application
  4. AMS

  5. { "links": { "self": "http://example.com/posts", "next": "http://example.com/posts?page[offset]=2", "last": "http://example.com/posts?page[offset]=10" },

    "data": [{ "type": "posts", "id": "1", "title": "JSON API paints my bikeshed!", "links": { "self": "http://example.com/posts/1", "author": { "self": "http://example.com/posts/1/links/author", "related": "http://example.com/posts/1/author", "linkage": { "type": "people", "id": "9" } }, "comments": { "self": "http://example.com/posts/1/links/comments", "related": "http://example.com/posts/1/comments", "linkage": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }], "included": [{ "type": "people", "id": "9", "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb", "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "body": "First!", "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "body": "I like XML better", "links": { "self": "http://example.com/comments/12" } }] }
  6. 2. JSONAPI { "links": { "self": "http://example.com/posts", "next": "http://example.com/posts?page[offset]=2", "last":

    "http://example.com/posts?page[offset]=10" }, "data": [{ "type": "posts", "id": "1", "title": "JSON API paints my bikeshed!", "links": { "self": "http://example.com/posts/1", "author": { "self": "http://example.com/posts/1/links/author", "related": "http://example.com/posts/1/author", "linkage": { "type": "people", "id": "9" } }, "comments": { "self": "http://example.com/posts/1/links/comments", "related": "http://example.com/posts/1/comments", "linkage": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }], "included": [{ "type": "people", "id": "9", "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb", "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "body": "First!", "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "body": "I like XML better", "links": { "self": "http://example.com/comments/12" } }] }
  7. 2. JSONAPI A standard for building APIs in JSON. {

    "links": { "self": "http://example.com/posts", "next": "http://example.com/posts?page[offset]=2", "last": "http://example.com/posts?page[offset]=10" }, "data": [{ "type": "posts", "id": "1", "title": "JSON API paints my bikeshed!", "links": { "self": "http://example.com/posts/1", "author": { "self": "http://example.com/posts/1/links/author", "related": "http://example.com/posts/1/author", "linkage": { "type": "people", "id": "9" } }, "comments": { "self": "http://example.com/posts/1/links/comments", "related": "http://example.com/posts/1/comments", "linkage": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }], "included": [{ "type": "people", "id": "9", "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb", "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "body": "First!", "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "body": "I like XML better", "links": { "self": "http://example.com/comments/12" } }] }
  8. 2. JSONAPI A standard for building APIs in JSON. {

    "links": { "self": "http://example.com/posts", "next": "http://example.com/posts?page[offset]=2", "last": "http://example.com/posts?page[offset]=10" }, "data": [{ "type": "posts", "id": "1", "title": "JSON API paints my bikeshed!", "links": { "self": "http://example.com/posts/1", "author": { "self": "http://example.com/posts/1/links/author", "related": "http://example.com/posts/1/author", "linkage": { "type": "people", "id": "9" } }, "comments": { "self": "http://example.com/posts/1/links/comments", "related": "http://example.com/posts/1/comments", "linkage": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }], "included": [{ "type": "people", "id": "9", "first-name": "Dan", "last-name": "Gebhardt", "twitter": "dgeb", "links": { "self": "http://example.com/people/9" } }, { "type": "comments", "id": "5", "body": "First!", "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "body": "I like XML better", "links": { "self": "http://example.com/comments/12" } }] }
  9. +

  10. class PostsController < ApplicationController def index @posts = Post.all render

    json: @posts end def show @post = Post.find(params[:id]) render json: @post end end
  11. class PostSerializer < ActiveModel::Serializer attributes :title, :body, :comments_count def title

    "Post - #{object.title}" end def comments_count object.comments.size end end
  12. class PostSerializer < ActiveModel::Serializer attributes :title, :body, :comments_count def title

    "Post - #{object.title}" end def comments_count object.comments.size end end
  13. class PostSerializer < ActiveModel::Serializer cache only: [:title] attributes :title, :body,

    :comments_count def title "Post - #{object.title}" end def comments_count object.comments.size end end
  14. class PostSerializer < ActiveModel::Serializer cache except: [:comments_count] attributes :title, :body,

    :comments_count def title "Post - #{object.title}" end def comments_count object.comments.size end end
  15. @post = Post.create(post_params) render json: @post, statue: :created end def

    post_params PostSerialization.deserialize(params) end
  16. def create @post = Post.create(post_params) render json: @post, status: :created

    end def post_params PostSerialization.deserialize(params) end