SlideShare a Scribd company logo
BUILDINg BETTER
WITH railS
Devils Tower, WY
web APIS
@caikeCarlos Souza
Code School
codeschool.com
tryruby.org
railsforzombies.org
Building Better Web APIs with Rails
perfect
rails web app
Deadline
Budget
Features
Tests
“We need a snappier
experience”
“We’ve detected the majority
of our visitors come from
mobile devices. 



We need to launch a native app

as soon as possible!”
“Does our web app
expose an API ?”
• Routes
• CONNEG
• AUTH
• VERSION
• Tests
endpoints, resources and
url-to-controller mappings
ROUTES
URLs are very important
/gists
/gists/public
/gists/starred
Building Better Web APIs with Rails
resources :projects
GET

POST

PATCH (PUT) 

DELETE
!
!
...
Projects#index
Projects#create
Projects#show
Projects#update
Projects#destroy
...
paths methods actions
/projects
/projects/:id
resources :projects
paths
/projects/archived

/projects/:id/archive

/projects
/projects/:id
?????
resources :projects
end
end
end
member do	
post 'archive'


collection do	
get 'archived'
do


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived'
post 'create_review'


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived', to: 'archived_projects#index'
, to: 'active_projects#index'
, to: 'suspended_projects#index'
, to: 'archived_projects#create'
, to: 'active_projects#create'
, to: 'suspended_projects#create'
post 'create_review'


!
get 'active'	
get 'suspended'	
!
!
!
post 'activate'	
post 'suspend'	
!
!
resources :projects
end
end
end
do
member do	
post 'archive'


collection do	
get 'archived'
resources :reviews, only: :create
, to: 'archived_projects#index'
, to: 'active_projects#index'
, to: 'suspended_projects#index'
, to: 'archived_projects#create'
, to: 'active_projects#create'
, to: 'suspended_projects#create'
app/controllers/api/projects_controller.rb
module Api	
class ProjectsController < ApplicationController	
def index	
...	
end	
end	
end
ActiveSupport::Inflector.inflections(:en) do |inflect|	
inflect.acronym 'API'	
end
config/initializers/inflections.rb
module API	
class ProjectsController < ApplicationController	
def index	
...	
end	
end	
end
connegcontent negotiation
Client A
API
I’m a Rich Java$cript Application 

and I want JSON!
Hey, I’m an Enterprise Java Application
and I want XML! (Ha Ha, Business!)
¯_(ツ)_/¯
Oi, soy un browser e quiero HTML!
response in JSON
respuesta en HTML
response in XML
Client B
Client C
content negotiation
The process in which client and server
determine the best representation for a response

when many are available.
/projects.json
GET /projects

Accept: application/json
vs.
Rails nicety
Part of the HTTP spec
client requests
responders
extracted out to 

responders gem
in Rails 4.2
module API	
class ProjectsController < ApplicationController	
respond_to :json, :xml	
!
def index	
@projects = Project.all	
!
respond_with(@projects)	
end	
end	
end
calls #to_json
calls #to_xml
respond_to
module API	
class ProjectsController < ApplicationController	
def index	
@projects = Project.recent	
!
respond_to do |format|	
format.json { render json: @projects, status: 200 }	
format.xml { render xml: @projects, status: 200 }	
end	
end	
end	
end
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
https://github.com/rails/jbuilder
class ProjectSerializer < ActiveModel::Serializer	
attributes :id, :title, :amount	
!
embed :ids, include: true	
has_many :products	
end
defaults to JSON-API
https://github.com/rails-api/active_model_serializers
ActiveModel::Serializers
module SongsRepresenter	
include Roar::JSON::JsonApi	
name :songs	
!
property :id	
property :title	
end
class SongRepresenter < Roar::Decorator	
include Roar::JSON::JsonApi	
name :songs	
!
property :id	
property :title	
end
https://github.com/apotonick/roar
using Mixins using Decorators
Roar
AUTHenticationpreventing unauthorized access
to protected resources
• Quick and Simple
• Reutilizes existing credentials
• HTTP spec (RFC 2617)
http basic AUTH
http basic AUTH
module API	
class ProjectsController < ApplicationController	
before_action :authenticate_or_request	
!
protected	
!
def authenticate_or_request	
authenticate_or_request_with_http_basic do |user, pwd|	
User.authenticate(user, pwd)	
end	
end	
end	
end
use the -u option
$ curl -I http://carlos:secret@localhost:3000/projects	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
$ curl -Iu 'carlos:secret' http://localhost:3000/projects	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
http basic AUTH with curl
• Can easily expire or regenerate tokens.
• Any vulnerability is limited to API access.
• Multiple tokens for each user.
• Different access rules can be implemented.
API
Projects
Forum
Admin
Client A
token based auth
token for the Backpack API
providing the token
Typically available out-of-band
on a user settings page
token for the Digital Ocean API
For security purposes, 

some services will only display
the access token once.
providing the token
token based auth
module API	
class ProjectsController < ApplicationController	
before_action :authenticate_or_request	
!
protected	
!
def authenticate_or_request	
authenticate_or_request_with_http_token do |token, opt|	
User.find_by(auth_token: token)	
end	
end	
end	
end
UUID - Universally Unique Identifier
GENERATING TOKENS
RFC 4122
We can use the Ruby standard library
SecureRandom.uuid
f4ea855f-d303-43e6-bee3-94581c0ecb21
90ab3255-ce33-4022-8349-b7979655b07c
371c760d-2539-41b9-b665-98c255d4c323
...
GENERATING TOKENS
end
def generate_auth_token
.gsub(/-/,'')
end
omits the hyphensSecureRandom.uuid
class User < ActiveRecord::Base	
before_create :set_auth_token	
!
private	
!
def set_auth_token	
return if auth_token.present?

self.auth_token = generate_auth_token	
end	
!
a47a8e54b11c4de5a4a351734c80a14a
9fa8a147b10c4efca3e8592b3a1c2729
823c1c984d504f66a2e6cbb2eb69e842
...
GENERATING TOKENS
$ curl -IH "Authorization: Token token=16d7d6089b8fe0c5e19bfe10bb156832" 	
http://localhost:3000/episodes	
!
HTTP/1.1 200 OK	
Content-Type: application/json; charset=utf-8
use the -H option
token based auth com curl
versioning resources
Version
MAJOR

incompatible changes


MINOR

backwards-compatible changes


PATCH

backwards-compatible bug fixes
http://semver.org/Semantic versioning
Works great for software libraries
V1/V1
feature X, feature Y
/V2
feature X, feature Y,
feature Z
Compatible changes:
• addition of a new format (i.e. JSON, XML )
• addition of a new property on a resource
• renaming of an end-point (use 3xx status code!)
• Only use major version.
• Changes cannot break existing clients.
• No need to bump version on compatible changes.
versioning services
410 Gone
https://www.mnot.net/blog/2012/12/04/api-evolution
“The biggest way to avoid new 

major versions is to make as many 

of your changes backwards-compatible 

as possible”
TESTSautomated verification
API
Unit Tests
testing apis
Not the time nor place to test business logic
API
• Status Code
• Mime Types
• Authentication
WHAT SHOULD WE TEST ?
API
HOW SHOULD WE TEST ?
Requesting endpoints and verifying responses
$ rails g integration_test <doing-something>
testing status code
require 'test_helper'	
!
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	
!
test 'returns list of projects' do	
get '/projects'	
assert_equal 200, response.status	
refute_empty response.body	
end	
end
testing status code
require 'test_helper'	
!
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	
!
test 'returns list of projects' do	
get '/projects'	
assert_equal 200, response.status	
refute_empty response.body	
end	
end
testing mime types
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	


test 'returns projects in JSON' do	
get '/projects', {}, { 'Accept' => Mime::JSON }	
assert_equal Mime::JSON, response.content_type	
end	
test 'returns projects in XML' do	
get '/projects', {}, { 'Accept' => Mime::XML }	
assert_equal Mime::XML, response.content_type	
end	
end
testing mime types
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { host! 'api.example.com' }	


test 'returns projects in JSON' do	
get '/projects', {}, { 'Accept' => Mime::JSON }	
assert_equal Mime::JSON, response.content_type	
end	
test 'returns projects in XML' do	
get '/projects', {}, { 'Accept' => Mime::XML }	
assert_equal Mime::XML, response.content_type	
end	
end
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { @user = User.create! }	
setup { host! 'api.example.com' }	
!
test 'valid authentication with token' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"}	
assert_equal 200, response.status	
assert_equal Mime::JSON, response.content_type	
end	
!
test 'invalid authentication' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" }	
assert_equal 401, response.status	
end	
end
testing access rules
class ListingProjectsTest < ActionDispatch::IntegrationTest	
setup { @user = User.create! }	
setup { host! 'api.example.com' }	
!
test 'valid authentication with token' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"}	
assert_equal 200, response.status	
assert_equal Mime::JSON, response.content_type	
end	
!
test 'invalid authentication' do	
get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" }	
assert_equal 401, response.status	
end	
end
testing access rules
railsapis.codeschool.com
Thank you
BUILDINg BETTER
WITH railS@caikeCarlos Souza
Code School
web APIS
Devils Tower, WY

More Related Content

PPTX
Ruby On Grape
PPTX
Building RESTful APIs w/ Grape
PDF
Get cfml Into the Box 2018
PDF
Effectively Testing Services - Burlington Ruby Conf
PDF
Do you want a SDK with that API? (Nordic APIS April 2014)
PDF
Serverless in production, an experience report (linuxing in london)
PPTX
RESTful API Design Best Practices Using ASP.NET Web API
PDF
Serverless in Production, an experience report (cloudXchange)
Ruby On Grape
Building RESTful APIs w/ Grape
Get cfml Into the Box 2018
Effectively Testing Services - Burlington Ruby Conf
Do you want a SDK with that API? (Nordic APIS April 2014)
Serverless in production, an experience report (linuxing in london)
RESTful API Design Best Practices Using ASP.NET Web API
Serverless in Production, an experience report (cloudXchange)

What's hot (20)

PDF
Behavior Driven Development with Cucumber
PPTX
The REST And Then Some
PDF
Introduction to plugin development
PDF
Scaling your Android App With Modularization
PPTX
Test automation with Cucumber-JVM
PDF
Finding Restfulness - Madrid.rb April 2014
PPTX
django Forms in a Web API World
PPTX
REST API Best Practices & Implementing in Codeigniter
PDF
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
PDF
Enter the app era with ruby on rails
PDF
Rails 4.0
PDF
Refactoring @ Mindvalley: Smells, Techniques and Patterns
PPTX
Calabash for iPhone apps
KEY
Motion Django Meetup
PDF
Observability and Troubleshooting in Forge
PPTX
Workshop Laravel 5.2
PDF
Building Beautiful REST APIs with ASP.NET Core
PDF
Browser-level testing
PDF
Serverless observability - a hero's perspective
PDF
REST full API Design
Behavior Driven Development with Cucumber
The REST And Then Some
Introduction to plugin development
Scaling your Android App With Modularization
Test automation with Cucumber-JVM
Finding Restfulness - Madrid.rb April 2014
django Forms in a Web API World
REST API Best Practices & Implementing in Codeigniter
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
Enter the app era with ruby on rails
Rails 4.0
Refactoring @ Mindvalley: Smells, Techniques and Patterns
Calabash for iPhone apps
Motion Django Meetup
Observability and Troubleshooting in Forge
Workshop Laravel 5.2
Building Beautiful REST APIs with ASP.NET Core
Browser-level testing
Serverless observability - a hero's perspective
REST full API Design
Ad

Viewers also liked (20)

PPT
Scalability for Startups (Frank Mashraqi, Startonomics SF 2008)
PPTX
A Local SEO Case Study
PDF
Building an API in Rails without Realizing It
PDF
SEO Case Study: Self Storage Industry
PDF
What Academia Can Learn from Open Source
PDF
Open Source Systems Administration
PDF
What Does Big Data Really Mean for Your Business?
PDF
The PHP Renaissance
PDF
Lessons Learned with Distributed Systems at Bitly
PPTX
Considerations for Operating an OpenStack Cloud
PPTX
All Things Open Opening Keynote
PDF
Building the iRODS Consortium
PDF
The Gurubox Project: Open Source Troubleshooting Tools
PDF
Open Source in Healthcare
PDF
Open Source & The Internet of Things
PDF
The Ember.js Framework - Everything You Need To Know
PDF
Stop Worrying & Love the SQL - A Case Study
PDF
Trademarks and Your Free and Open Source Software Project
PPTX
I Know It Was MEAN, But I Cut the Cord to LAMP Anyway
Scalability for Startups (Frank Mashraqi, Startonomics SF 2008)
A Local SEO Case Study
Building an API in Rails without Realizing It
SEO Case Study: Self Storage Industry
What Academia Can Learn from Open Source
Open Source Systems Administration
What Does Big Data Really Mean for Your Business?
The PHP Renaissance
Lessons Learned with Distributed Systems at Bitly
Considerations for Operating an OpenStack Cloud
All Things Open Opening Keynote
Building the iRODS Consortium
The Gurubox Project: Open Source Troubleshooting Tools
Open Source in Healthcare
Open Source & The Internet of Things
The Ember.js Framework - Everything You Need To Know
Stop Worrying & Love the SQL - A Case Study
Trademarks and Your Free and Open Source Software Project
I Know It Was MEAN, But I Cut the Cord to LAMP Anyway
Ad

Similar to Building Better Web APIs with Rails (20)

PDF
Test-Driven Documentation for your REST(ful) service
ZIP
Palestra VCR
KEY
Api development with rails
PDF
Nordic APIs - Automatic Testing of (RESTful) API Documentation
PPTX
Araport Workshop Tutorial 2: Authentication and the Agave Profiles Service
PPTX
API Workshop: Deep dive into REST APIs
PDF
API Days Paris - Automatic Testing of (RESTful) API Documentation
PDF
Rack
PDF
Building APIs in an easy way using API Platform
PDF
JSON REST API for WordPress
PDF
Continuous Integration and Deployment Best Practices on AWS
PPTX
KazooCon 2014 - Introduction to Kazoo APIs!
PDF
API Days Australia - Automatic Testing of (RESTful) API Documentation
PPTX
API testing - Japura.pptx
PPT
Streamlined Geek Talk
PDF
Introduction à Ruby
KEY
Wider than rails
PPTX
An introduction to the API for OnTime for IBM
PPTX
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
PPTX
Women Who Code - RSpec JSON API Workshop
Test-Driven Documentation for your REST(ful) service
Palestra VCR
Api development with rails
Nordic APIs - Automatic Testing of (RESTful) API Documentation
Araport Workshop Tutorial 2: Authentication and the Agave Profiles Service
API Workshop: Deep dive into REST APIs
API Days Paris - Automatic Testing of (RESTful) API Documentation
Rack
Building APIs in an easy way using API Platform
JSON REST API for WordPress
Continuous Integration and Deployment Best Practices on AWS
KazooCon 2014 - Introduction to Kazoo APIs!
API Days Australia - Automatic Testing of (RESTful) API Documentation
API testing - Japura.pptx
Streamlined Geek Talk
Introduction à Ruby
Wider than rails
An introduction to the API for OnTime for IBM
Survival Strategies for API Documentation: Presentation to Southwestern Ontar...
Women Who Code - RSpec JSON API Workshop

More from All Things Open (20)

PDF
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
PPTX
Big Data on a Small Budget: Scalable Data Visualization for the Rest of Us - ...
PDF
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
PDF
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
PDF
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
PDF
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
PDF
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
PPTX
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
PDF
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
PDF
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
PPTX
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
PDF
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
PPTX
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
PDF
The Death of the Browser - Rachel-Lee Nabors, AgentQL
PDF
Making Operating System updates fast, easy, and safe
PDF
Reshaping the landscape of belonging to transform community
PDF
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
PDF
Integrating Diversity, Equity, and Inclusion into Product Design
PDF
The Open Source Ecosystem for eBPF in Kubernetes
PDF
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman
Agentic AI for Developers and Data Scientists Build an AI Agent in 10 Lines o...
Big Data on a Small Budget: Scalable Data Visualization for the Rest of Us - ...
AI 3-in-1: Agents, RAG, and Local Models - Brent Laster
Let's Create a GitHub Copilot Extension! - Nick Taylor, Pomerium
Leveraging Pre-Trained Transformer Models for Protein Function Prediction - T...
Gen AI: AI Agents - Making LLMs work together in an organized way - Brent Las...
You Don't Need an AI Strategy, But You Do Need to Be Strategic About AI - Jes...
DON’T PANIC: AI IS COMING – The Hitchhiker’s Guide to AI - Mark Hinkle, Perip...
Fine-Tuning Large Language Models with Declarative ML Orchestration - Shivay ...
Leveraging Knowledge Graphs for RAG: A Smarter Approach to Contextual AI Appl...
Artificial Intelligence Needs Community Intelligence - Sriram Raghavan, IBM R...
Don't just talk to AI, do more with AI: how to improve productivity with AI a...
Open-Source GenAI vs. Enterprise GenAI: Navigating the Future of AI Innovatio...
The Death of the Browser - Rachel-Lee Nabors, AgentQL
Making Operating System updates fast, easy, and safe
Reshaping the landscape of belonging to transform community
The Unseen, Underappreciated Security Work Your Maintainers May (or may not) ...
Integrating Diversity, Equity, and Inclusion into Product Design
The Open Source Ecosystem for eBPF in Kubernetes
Open Source Privacy-Preserving Metrics - Sarah Gran & Brandon Pitman

Recently uploaded (20)

DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Empathic Computing: Creating Shared Understanding
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Encapsulation theory and applications.pdf
The AUB Centre for AI in Media Proposal.docx
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Mobile App Security Testing_ A Comprehensive Guide.pdf
Spectral efficient network and resource selection model in 5G networks
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Approach and Philosophy of On baking technology
Chapter 3 Spatial Domain Image Processing.pdf
Empathic Computing: Creating Shared Understanding
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Encapsulation_ Review paper, used for researhc scholars
Diabetes mellitus diagnosis method based random forest with bat algorithm
The Rise and Fall of 3GPP – Time for a Sabbatical?
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
MYSQL Presentation for SQL database connectivity
Digital-Transformation-Roadmap-for-Companies.pptx
Per capita expenditure prediction using model stacking based on satellite ima...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Encapsulation theory and applications.pdf

Building Better Web APIs with Rails

  • 1. BUILDINg BETTER WITH railS Devils Tower, WY web APIS @caikeCarlos Souza Code School
  • 7. “We need a snappier experience”
  • 8. “We’ve detected the majority of our visitors come from mobile devices. 
 
 We need to launch a native app
 as soon as possible!”
  • 9. “Does our web app expose an API ?”
  • 10. • Routes • CONNEG • AUTH • VERSION • Tests
  • 12. URLs are very important /gists /gists/public /gists/starred
  • 14. resources :projects GET
 POST
 PATCH (PUT) 
 DELETE ! ! ... Projects#index Projects#create Projects#show Projects#update Projects#destroy ... paths methods actions /projects /projects/:id
  • 16. resources :projects end end end member do post 'archive' 
 collection do get 'archived' do
  • 17. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived' post 'create_review'
  • 18. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived', to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create' post 'create_review'
  • 19. 
 ! get 'active' get 'suspended' ! ! ! post 'activate' post 'suspend' ! ! resources :projects end end end do member do post 'archive' 
 collection do get 'archived' resources :reviews, only: :create , to: 'archived_projects#index' , to: 'active_projects#index' , to: 'suspended_projects#index' , to: 'archived_projects#create' , to: 'active_projects#create' , to: 'suspended_projects#create'
  • 20. app/controllers/api/projects_controller.rb module Api class ProjectsController < ApplicationController def index ... end end end
  • 21. ActiveSupport::Inflector.inflections(:en) do |inflect| inflect.acronym 'API' end config/initializers/inflections.rb module API class ProjectsController < ApplicationController def index ... end end end
  • 23. Client A API I’m a Rich Java$cript Application 
 and I want JSON! Hey, I’m an Enterprise Java Application and I want XML! (Ha Ha, Business!) ¯_(ツ)_/¯ Oi, soy un browser e quiero HTML! response in JSON respuesta en HTML response in XML Client B Client C content negotiation The process in which client and server determine the best representation for a response
 when many are available.
  • 24. /projects.json GET /projects
 Accept: application/json vs. Rails nicety Part of the HTTP spec client requests
  • 25. responders extracted out to 
 responders gem in Rails 4.2 module API class ProjectsController < ApplicationController respond_to :json, :xml ! def index @projects = Project.all ! respond_with(@projects) end end end
  • 26. calls #to_json calls #to_xml respond_to module API class ProjectsController < ApplicationController def index @projects = Project.recent ! respond_to do |format| format.json { render json: @projects, status: 200 } format.xml { render xml: @projects, status: 200 } end end end end
  • 27. 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 https://github.com/rails/jbuilder
  • 28. class ProjectSerializer < ActiveModel::Serializer attributes :id, :title, :amount ! embed :ids, include: true has_many :products end defaults to JSON-API https://github.com/rails-api/active_model_serializers ActiveModel::Serializers
  • 29. module SongsRepresenter include Roar::JSON::JsonApi name :songs ! property :id property :title end class SongRepresenter < Roar::Decorator include Roar::JSON::JsonApi name :songs ! property :id property :title end https://github.com/apotonick/roar using Mixins using Decorators Roar
  • 31. • Quick and Simple • Reutilizes existing credentials • HTTP spec (RFC 2617) http basic AUTH
  • 32. http basic AUTH module API class ProjectsController < ApplicationController before_action :authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_basic do |user, pwd| User.authenticate(user, pwd) end end end end
  • 33. use the -u option $ curl -I http://carlos:secret@localhost:3000/projects ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 $ curl -Iu 'carlos:secret' http://localhost:3000/projects ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 http basic AUTH with curl
  • 34. • Can easily expire or regenerate tokens. • Any vulnerability is limited to API access. • Multiple tokens for each user. • Different access rules can be implemented. API Projects Forum Admin Client A token based auth
  • 35. token for the Backpack API providing the token Typically available out-of-band on a user settings page
  • 36. token for the Digital Ocean API For security purposes, 
 some services will only display the access token once. providing the token
  • 37. token based auth module API class ProjectsController < ApplicationController before_action :authenticate_or_request ! protected ! def authenticate_or_request authenticate_or_request_with_http_token do |token, opt| User.find_by(auth_token: token) end end end end
  • 38. UUID - Universally Unique Identifier GENERATING TOKENS RFC 4122
  • 39. We can use the Ruby standard library SecureRandom.uuid f4ea855f-d303-43e6-bee3-94581c0ecb21 90ab3255-ce33-4022-8349-b7979655b07c 371c760d-2539-41b9-b665-98c255d4c323 ... GENERATING TOKENS
  • 40. end def generate_auth_token .gsub(/-/,'') end omits the hyphensSecureRandom.uuid class User < ActiveRecord::Base before_create :set_auth_token ! private ! def set_auth_token return if auth_token.present?
 self.auth_token = generate_auth_token end ! a47a8e54b11c4de5a4a351734c80a14a 9fa8a147b10c4efca3e8592b3a1c2729 823c1c984d504f66a2e6cbb2eb69e842 ... GENERATING TOKENS
  • 41. $ curl -IH "Authorization: Token token=16d7d6089b8fe0c5e19bfe10bb156832" http://localhost:3000/episodes ! HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 use the -H option token based auth com curl
  • 43. MAJOR
 incompatible changes 
 MINOR
 backwards-compatible changes 
 PATCH
 backwards-compatible bug fixes http://semver.org/Semantic versioning Works great for software libraries
  • 44. V1/V1 feature X, feature Y /V2 feature X, feature Y, feature Z Compatible changes: • addition of a new format (i.e. JSON, XML ) • addition of a new property on a resource • renaming of an end-point (use 3xx status code!) • Only use major version. • Changes cannot break existing clients. • No need to bump version on compatible changes. versioning services
  • 46. https://www.mnot.net/blog/2012/12/04/api-evolution “The biggest way to avoid new 
 major versions is to make as many 
 of your changes backwards-compatible 
 as possible”
  • 48. API Unit Tests testing apis Not the time nor place to test business logic
  • 49. API • Status Code • Mime Types • Authentication WHAT SHOULD WE TEST ?
  • 50. API HOW SHOULD WE TEST ? Requesting endpoints and verifying responses $ rails g integration_test <doing-something>
  • 51. testing status code require 'test_helper' ! class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
  • 52. testing status code require 'test_helper' ! class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } ! test 'returns list of projects' do get '/projects' assert_equal 200, response.status refute_empty response.body end end
  • 53. testing mime types class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } 
 test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
  • 54. testing mime types class ListingProjectsTest < ActionDispatch::IntegrationTest setup { host! 'api.example.com' } 
 test 'returns projects in JSON' do get '/projects', {}, { 'Accept' => Mime::JSON } assert_equal Mime::JSON, response.content_type end test 'returns projects in XML' do get '/projects', {}, { 'Accept' => Mime::XML } assert_equal Mime::XML, response.content_type end end
  • 55. class ListingProjectsTest < ActionDispatch::IntegrationTest setup { @user = User.create! } setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules
  • 56. class ListingProjectsTest < ActionDispatch::IntegrationTest setup { @user = User.create! } setup { host! 'api.example.com' } ! test 'valid authentication with token' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}"} assert_equal 200, response.status assert_equal Mime::JSON, response.content_type end ! test 'invalid authentication' do get '/projects', {}, { 'Authorization' => "Token token=#{@user.auth_token}fake" } assert_equal 401, response.status end end testing access rules
  • 58. Thank you BUILDINg BETTER WITH railS@caikeCarlos Souza Code School web APIS Devils Tower, WY