SlideShare a Scribd company logo
Using	
  Sinatra	
  to	
  Build	
  
REST	
  APIs	
  in	
  Ruby	
  
James	
  Higginbotham	
  
API	
  Architect	
  
@launchany	
  
Introduc?on	
  
WHAT	
  IS	
  SINATRA?	
  
Sinatra	
  is	
  a	
  DSL	
  for	
  quickly	
  
crea<ng	
  web	
  applica<ons	
  in	
  
Ruby	
  
# hi.rb
require 'rubygems’
require 'sinatra'
get '/' do
'Hello world!’
end
$ gem install sinatra
$ ruby hi.rb
== Sinatra has taken the stage ...
>> Listening on 0.0.0.0:4567
$ curl http://0.0.0.0:4567
Hello World
HOW	
  DOES	
  SINATRA	
  WORK?	
  
Rou?ng:	
  Verb	
  +	
  PaCern	
  +	
  Block	
  
post ’/' do
.. block ..
end
Rou?ng:	
  Named	
  Params	
  
get '/:id' do
model = MyModel.find( params[:id] )
...
end
Rou?ng:	
  Splat	
  Support	
  
get '/say/*/to/*' do
# matches /say/hello/to/world
params['splat'] # => ["hello", "world"]
...
end
get '/download/*.*' do
# matches /download/path/to/file.xml
params['splat'] # => ["path/to/file", "xml"]
...
end
Rou?ng:	
  Regex	
  Support	
  
get /A/hello/([w]+)z/ do
"Hello, #{params['captures'].first}!”
...
end
Rou?ng:	
  Op?onal	
  Parameters	
  
get '/posts.?:format?' do
# matches "GET /posts" and
# any extension "GET /posts.rss", "GET /posts.xml" etc.
end
Rou?ng:	
  URL	
  Query	
  Parameters	
  
get '/posts' do
# matches "GET /posts?title=foo&author=bar"
title = params['title']
author = params['author']
# uses title and author variables;
# query is optional to the /posts route
End
Rou?ng:	
  Condi?onal	
  Matching	
  
get '/', :host_name => /^admin./ do
"Admin Area, Access denied!"
end
get '/', :provides => 'html' do
haml :index
end
get '/', :provides => ['rss', 'atom', 'xml'] do
builder :feed
end
Rou?ng:	
  Custom	
  Condi?ons	
  
set(:probability) { |value| condition { rand <= value } }
get '/win_a_car', :probability => 0.1 do
"You won!"
end
get '/win_a_car' do
"Sorry, you lost."
End
Returning	
  Results	
  
# 1. String containing the body and default code of 200
get '/' do
'Hello world!’
end
# 2. Response code + body
get '/' do
[200, 'Hello world!’]
end
# 3. Response code + headers + body
get '/' do
[200, {'Content-Type' => 'text/plain'}, 'Hello world!’]
end
BUILDING	
  ON	
  RACK	
  
Hello	
  World	
  with	
  Rack	
  
# hello_world.rb
require 'rack'
require 'rack/server’
class HelloWorldApp
def self.call(env)
[200, {}, 'Hello World’]
end
end
Rack::Server.start :app => HelloWorldApp
Rack	
  env	
  
# hello_world.rb
require 'rack'
require 'rack/server’
class HelloWorldApp
def self.call(env)
[200, {},
"Hello World. You said: #{env['QUERY_STRING']}"]
end
end
Rack::Server.start :app => HelloWorldApp
Typical	
  env	
  
{
"SERVER_SOFTWARE"=>"thin 1.4.1 codename Chromeo",
"SERVER_NAME"=>"localhost",
"rack.input"=>#<StringIO:0x007fa1bce039f8>,
"rack.version"=>[1, 0],
"rack.errors"=>#<IO:<STDERR>>,
"rack.multithread"=>false,
"rack.multiprocess"=>false,
"rack.run_once"=>false,
"REQUEST_METHOD"=>"GET",
"REQUEST_PATH"=>"/favicon.ico",
"PATH_INFO"=>"/favicon.ico",
"REQUEST_URI"=>"/favicon.ico",
"HTTP_VERSION"=>"HTTP/1.1",
"HTTP_HOST"=>"localhost:8080",
"HTTP_CONNECTION"=>"keep-alive",
"HTTP_ACCEPT"=>"*/*”,
...
Typical	
  env	
  (con’t)	
  
...
"HTTP_USER_AGENT"=>
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4)
AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47
Safari/536.11",
"HTTP_ACCEPT_ENCODING"=>"gzip,deflate,sdch",
"HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q=0.8",
"HTTP_ACCEPT_CHARSET"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.3",
"HTTP_COOKIE"=> "_gauges_unique_year=1;
_gauges_unique_month=1",
"GATEWAY_INTERFACE"=>"CGI/1.2",
"SERVER_PORT"=>"8080",
"QUERY_STRING"=>"",
"SERVER_PROTOCOL"=>"HTTP/1.1",
"rack.url_scheme"=>"http",
"SCRIPT_NAME"=>"",
"REMOTE_ADDR"=>"127.0.0.1",
...
}
The	
  Rack::Request	
  Wrapper	
  
class HelloWorldApp
def self.call(env)
request = Rack::Request.new(env)
request.params # contains the union of GET and POST
params
request.xhr? # requested with AJAX
require.body # the incoming request IO stream
if request.params['message']
[200, {}, request.params['message']]
else
[200, {}, 'Say something to me!']
end
end
end
Rack	
  Middleware	
  
u  Rack	
  allows	
  for	
  chaining	
  mul?ple	
  call()	
  
methods	
  
u  We	
  can	
  do	
  anything	
  we	
  want	
  within	
  each	
  call()	
  
u  This	
  includes	
  separa?ng	
  behavior	
  into	
  
reusable	
  classes	
  (e.g.	
  across	
  Sinatra	
  and	
  Rails)	
  
u  SRP	
  (Single	
  Responsibility	
  Principle)	
  
– Each	
  class	
  has	
  a	
  single	
  responsibility	
  
– Our	
  app	
  is	
  composed	
  of	
  mul?ple	
  classes	
  that	
  each	
  
do	
  one	
  thing	
  well	
  
Rack::Builder	
  for	
  Middleware	
  
# this returns an app that responds to call cascading down
# the list of middlewares.
app = Rack::Builder.new do
use Rack::Etag # Add an ETag
use Rack::ConditionalGet # Support Caching
use Rack::Deflator # GZip
run HelloWorldApp # Say Hello
end
Rack::Server.start :app => app
# Resulting call tree:
# Rack::Etag
# Rack::ConditionalGet
# Rack::Deflator
# HelloWorldApp
Using	
  the	
  Rackup	
  Command	
  
u  Combines	
  all	
  of	
  these	
  concepts	
  into	
  a	
  config	
  
u  Will	
  start	
  a	
  web	
  process	
  with	
  your	
  Rack	
  app	
  
u  Central	
  loca?on	
  for	
  requires,	
  bootstrapping	
  
u  Enables	
  middleware	
  to	
  be	
  configured	
  as	
  well	
  
u  Default	
  filename	
  is	
  config.ru	
  
u  Used	
  to	
  bootstrap	
  Rails	
  
Using	
  Rackup	
  
# config.ru
# HelloWorldApp defintion
# EnsureJsonResponse defintion
# Timer definition
use Timer
use EnsureJsonResponse
run HelloWorldApp
$ rackup –p 4567
Using	
  Mul?ple	
  Sinatra	
  Apps	
  
u  Rackup	
  allows	
  for	
  moun?ng	
  mul?ple	
  Sinatra	
  
Apps	
  
u  This	
  allows	
  for	
  more	
  modular	
  APIs	
  
u  Recommend	
  one	
  Sinatra	
  app	
  per	
  top-­‐level	
  
resource	
  
Moun?ng	
  Mul?ple	
  Sinatra	
  Apps	
  
# config.ru
require 'sinatra'
require 'app/auth_api'
require 'app/users_api'
require 'app/organizations_api'
map "/auth" do
run AuthApi
end
map "/users" do
run UsersApi
end
map "/organizations" do
run OrganizationsApi
end
Important:	
  Require	
  !=	
  Automa?c	
  
u  Must	
  manage	
  your	
  own	
  requires	
  
u  No	
  free	
  ride	
  (like	
  with	
  Rails)	
  
u  This	
  means	
  order	
  of	
  requires	
  is	
  important!	
  
WHAT	
  IS	
  A	
  REST	
  API?	
  
Mul?ple	
  API	
  Design	
  Choices	
  
u  RPC-­‐based	
  
– Uses	
  HTTP	
  for	
  transport	
  only	
  
– Endpoints	
  are	
  not	
  unique,	
  only	
  the	
  payload	
  
– No	
  HTTP	
  caching	
  available	
  
– e.g.	
  POST	
  /getUserDetails,	
  POST	
  /createUser	
  
u  Resource-­‐based	
  
– Unique	
  URLs	
  for	
  resources	
  and	
  collec?ons	
  
– HTTP	
  caching	
  available	
  
– e.g.	
  GET	
  /users/{userId}	
  and	
  GET	
  /users	
  
Hypermedia	
  REST	
  
u  An	
  architectural	
  style,	
  with	
  constraints	
  
u  A	
  set	
  of	
  constraints,	
  usually	
  on	
  top	
  of	
  HTTP	
  
u  Not	
  a	
  standard;	
  builds	
  on	
  the	
  standard	
  of	
  
HTTP	
  
u  Mul?ple	
  content	
  types	
  (e.g.	
  JSON,	
  XML,	
  CSV)	
  
u  The	
  response	
  is	
  a	
  representa?on	
  of	
  the	
  
resource	
  state	
  (data)	
  plus	
  server-­‐side	
  state	
  in	
  
the	
  form	
  of	
  ac<ons/transi<ons	
  (links)	
  
BUILDING	
  AN	
  API	
  USING	
  SINATRA	
  
Resource	
  Lifecycle	
  using	
  Sinatra	
  
get '/users' do
.. list a resource collection (and search) ..
end
get '/users/:id' do
.. resource instance details ..
end
post '/users' do
.. create new resource ..
end
put '/users/:id' do
.. replace resource ..
End
delete ’/users/:id' do
.. annihilate resource ..
end
List	
  Resources	
  Example	
  
get '/users' do
# 1. capture any search filters using params[]
email_filter = params[:email]
# 2. build query and fetch results from database
if email_filter
users = User.where( email: email_filter ).all
else
users = User.all
# 3. marshal results to proper content type (e.g. JSON)
[200, users.to_json]
end
List	
  Resources	
  Example	
  
get '/users' do
# 1. capture any search filters using params[]
email_filter = params[:email]
# 2. build query and fetch results from database
if email_filter
users = User.where( email: email_filter ).all
else
users = User.all
# 3. marshal results to proper content type (e.g. JSON)
[200, users.to_json]
# Q: Which ORM should we use with Sinatra?
# Q: Can we customize the results format easily?
end
USEFUL	
  GEMS	
  
Selec?ng	
  an	
  ORM	
  
u  Ac?veRecord	
  
u  DataMapper	
  
u  Sequel	
  (my	
  favorite)	
  
– Flexible	
  as	
  it	
  supports	
  Datasets	
  and	
  Models	
  
Sequel	
  Datasets	
  Example	
  
require 'sequel'
DB = Sequel.sqlite # memory database
DB.create_table :items do
primary_key :id
String :name
Float :price
end
items = DB[:items] # Create a dataset
items.insert(:name => 'abc', :price => rand * 100)
items.insert(:name => 'def', :price => rand * 100)
items.insert(:name => 'ghi', :price => rand * 100)
puts "Item count: #{items.count}"
puts "The average price is: #{items.avg(:price)}”
Sequel	
  Model	
  Example	
  
require 'sequel'
DB = Sequel.sqlite # memory database
class Post < Sequel::Model
end
post = Post[123]
post = Post.new
post.title = 'hello world'
post.save
Select	
  a	
  Marshaling	
  Library	
  
u  Ac?veModel::Serializers	
  (AMS)	
  	
  
– Works	
  with	
  Kaminari	
  and	
  WillPaginate	
  
– Supported	
  by	
  Rails	
  core	
  team	
  
– One-­‐way	
  JSON	
  genera?on	
  only	
  
u  Roar+Representable	
  (my	
  favorite)	
  
– Works	
  with	
  and	
  without	
  Rails	
  
– Bi-­‐direc?onal	
  marshaling	
  
– Supports	
  JSON,	
  XML,	
  YAML,	
  hash	
  
Representable	
  
module SongRepresenter
include Representable::JSON
property :title
property :track
collection :composers
end
class Song < OpenStruct
end
song = Song.new(title: "Fallout", track: 1)
song.extend(SongRepresenter).to_json
> {"title":"Fallout","track":1}
song = Song.new.extend(SongRepresenter).from_json(%
{ {"title":"Roxanne"} })
> #<Song title="Roxanne">
Roar	
  +	
  Representable	
  
module SongRepresenter
include Roar::JSON
include Roar::Hypermedia
property :title
property :track
collection :composers
link :self do
"/songs/#{title}"
end
end
song = Song.new(title: "Fallout", track: 1)
song.extend(SongRepresenter).to_json
> {"title":"Fallout","track":1,"links":
[{"rel":"self","href":"/songs/Fallout"}]}"
Tools	
  for	
  Tes?ng	
  Your	
  API	
  
u  Unit	
  –	
  RSpec	
  
– Models,	
  helpers	
  
u  Integra?on	
  –	
  RSpec	
  
– Make	
  HTTP	
  calls	
  to	
  a	
  running	
  Sinatra	
  process	
  
– Controller-­‐focused	
  
u  Acceptance/BDD	
  –	
  RSpec,	
  Cucumber	
  
– Make	
  HTTP	
  calls	
  to	
  a	
  running	
  Sinatra	
  process	
  
– Use-­‐case/story	
  focused	
  
MATURING	
  YOUR	
  SINATRA	
  APPS	
  
Addi?onal	
  Gems	
  
u  faraday	
  –	
  HTTP	
  client	
  with	
  middleware	
  for	
  
tes?ng	
  and	
  3rd	
  party	
  API	
  integra?on	
  
u  xml-­‐simple	
  –	
  Easy	
  XML	
  parsing	
  and	
  genera?on	
  
u  faker	
  –	
  Generates	
  fake	
  names,	
  addresses,	
  etc.	
  
u  uuidtools	
  –	
  uuid	
  generator	
  when	
  incremen?ng	
  
integers	
  aren’t	
  good	
  enough	
  
u  bcrypt	
  –	
  Ruby	
  binding	
  for	
  OpenBSD	
  hashing	
  
algorithm,	
  to	
  secure	
  data	
  at	
  rest	
  
Addi?onal	
  Gems	
  (part	
  2)	
  
u  rack-­‐conneg	
  –	
  Content	
  nego?a?on	
  support	
  
get '/hello' do
response = { :message => 'Hello, World!' }
respond_to do |wants|
wants.json { response.to_json }
wants.xml { response.to_xml }
wants.other {
content_type 'text/plain'
error 406, "Not Acceptable"
}
end
end
curl -H "Accept: application/json" http://localhost:4567/
hello
Addi?onal	
  Gems	
  (part	
  3)	
  
u  hirb	
  –	
  Console	
  formaing	
  of	
  data	
  from	
  CLI,	
  
Rake	
  tasks	
  
irb>> Tag.last
+-----+-------------------------+-------------+
| id | created_at | description |
+-----+-------------------------+-------------+
| 907 | 2009-03-06 21:10:41 UTC | blah |
+-----+-------------------------+-------------+
1 row in set
Reloading	
  with	
  Shotgun	
  Gem	
  
u  No	
  automa?c	
  reload	
  of	
  classes	
  with	
  Sinatra	
  
u  Instead,	
  use	
  the	
  shotgun	
  gem:	
  
u  Note:	
  Only	
  works	
  with	
  Ruby	
  MRI	
  where	
  fork()	
  
is	
  available	
  (POSIX)	
  
$ gem install shotgun
$ shotgun config.ru
Puma	
  +	
  JRuby	
  
u  Ruby	
  MRI	
  is	
  geing	
  beCer	
  
u  JVM	
  is	
  faster	
  (2-­‐5x),	
  very	
  mature	
  (since	
  1997)	
  
u  High	
  performance	
  garbage	
  collectors,	
  na?ve	
  
threading,	
  JMX	
  management	
  extensions	
  
u  JDBC	
  libraries	
  very	
  mature	
  and	
  performant	
  for	
  
SQL-­‐based	
  access	
  
u  Puma	
  is	
  recommended	
  over	
  unicorn	
  for	
  JRuby	
  	
  
From	
  Sinatra	
  to	
  Padrino	
  
u  Padrino	
  provides	
  Rails-­‐like	
  environment	
  for	
  
Sinatra	
  
u  Build	
  in	
  Sinatra,	
  move	
  to	
  Padrino	
  when	
  
needed	
  
u  Generators,	
  pluggable	
  modules,	
  admin	
  
generator	
  
Resources	
  
u  Sinatra	
  Docs:	
  	
  
hCp://www.sinatrarb.com/intro.html	
  	
  
u  Introduc?on	
  to	
  Rack:	
  
hCp://hawkins.io/2012/07/rack_from_the_beginning/	
  	
  
u  Sequel	
  Gem:	
  
hCps://github.com/jeremyevans/sequel	
  	
  
u  Roar/Representable:	
  
hCps://github.com/apotonick/roar	
  	
  
hCps://github.com/apotonick/representable	
  	
  
Thanks	
  Ya’ll	
  
James	
  Higginbotham	
  
james@launchany.com	
  
hCp://launchany.com	
  	
  
@launchany	
  
	
  
Design	
  Beau?ful	
  APIs:	
  
hCp://TheApiDesignBook.com	
  	
  
QUESTIONS	
  

More Related Content

What's hot

Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Simplilearn
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
habib_786
 
introduction about REST API
introduction about REST APIintroduction about REST API
introduction about REST API
AmilaSilva13
 
RxJS - The Basics & The Future
RxJS - The Basics & The FutureRxJS - The Basics & The Future
RxJS - The Basics & The Future
Tracy Lee
 
laravel.pptx
laravel.pptxlaravel.pptx
laravel.pptx
asif290119
 
Web service Introduction
Web service IntroductionWeb service Introduction
Web service Introduction
Madhukar Kumar
 
Service discovery with Eureka and Spring Cloud
Service discovery with Eureka and Spring CloudService discovery with Eureka and Spring Cloud
Service discovery with Eureka and Spring Cloud
Marcelo Serpa
 
API for Beginners
API for BeginnersAPI for Beginners
API for Beginners
Gustavo De Vita
 
An Overview on Nuxt.js
An Overview on Nuxt.jsAn Overview on Nuxt.js
An Overview on Nuxt.js
Squash Apps Pvt Ltd
 
Docker Swarm 0.2.0
Docker Swarm 0.2.0Docker Swarm 0.2.0
Docker Swarm 0.2.0
Docker, Inc.
 
Linux crontab
Linux crontabLinux crontab
Linux crontab
Teja Bheemanapally
 
Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020
Microsoft 365 Developer
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
Nitin Pande
 
Rego Deep Dive
Rego Deep DiveRego Deep Dive
Rego Deep Dive
Torin Sandall
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
Dmitry Sheiko
 
React Router: React Meetup XXL
React Router: React Meetup XXLReact Router: React Meetup XXL
React Router: React Meetup XXL
Rob Gietema
 
Ssrf
SsrfSsrf
Asp.net control
Asp.net controlAsp.net control
Asp.net control
Paneliya Prince
 
Laravel introduction
Laravel introductionLaravel introduction
Laravel introduction
Simon Funk
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
Megha V
 

What's hot (20)

Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
 
ASP.NET Web API
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
 
introduction about REST API
introduction about REST APIintroduction about REST API
introduction about REST API
 
RxJS - The Basics & The Future
RxJS - The Basics & The FutureRxJS - The Basics & The Future
RxJS - The Basics & The Future
 
laravel.pptx
laravel.pptxlaravel.pptx
laravel.pptx
 
Web service Introduction
Web service IntroductionWeb service Introduction
Web service Introduction
 
Service discovery with Eureka and Spring Cloud
Service discovery with Eureka and Spring CloudService discovery with Eureka and Spring Cloud
Service discovery with Eureka and Spring Cloud
 
API for Beginners
API for BeginnersAPI for Beginners
API for Beginners
 
An Overview on Nuxt.js
An Overview on Nuxt.jsAn Overview on Nuxt.js
An Overview on Nuxt.js
 
Docker Swarm 0.2.0
Docker Swarm 0.2.0Docker Swarm 0.2.0
Docker Swarm 0.2.0
 
Linux crontab
Linux crontabLinux crontab
Linux crontab
 
Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
 
Rego Deep Dive
Rego Deep DiveRego Deep Dive
Rego Deep Dive
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
React Router: React Meetup XXL
React Router: React Meetup XXLReact Router: React Meetup XXL
React Router: React Meetup XXL
 
Ssrf
SsrfSsrf
Ssrf
 
Asp.net control
Asp.net controlAsp.net control
Asp.net control
 
Laravel introduction
Laravel introductionLaravel introduction
Laravel introduction
 
Introduction to JavaScript
Introduction to JavaScriptIntroduction to JavaScript
Introduction to JavaScript
 

Similar to Using Sinatra to Build REST APIs in Ruby

Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
Emanuele DelBono
 
Rack
RackRack
Sinatra and JSONQuery Web Service
Sinatra and JSONQuery Web ServiceSinatra and JSONQuery Web Service
Sinatra and JSONQuery Web Service
vvatikiotis
 
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
崇之 清水
 
Sinatra
SinatraSinatra
Sinatra
kevinreiss
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Masahiro Nagano
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
Wesley Beary
 
Socket applications
Socket applicationsSocket applications
Socket applications
João Moura
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
Wesley Beary
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
danwrong
 
Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
Rubyc Slides
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
Daniel Spector
 
Wider than rails
Wider than railsWider than rails
Wider than rails
Alexey Nayden
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
LittleBIGRuby
 
Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!
cloudbring
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
Itamar Hassin
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
sickill
 
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine YardHow I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
SV Ruby on Rails Meetup
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
davidchubbs
 

Similar to Using Sinatra to Build REST APIs in Ruby (20)

Sinatra for REST services
Sinatra for REST servicesSinatra for REST services
Sinatra for REST services
 
Rack
RackRack
Rack
 
Sinatra and JSONQuery Web Service
Sinatra and JSONQuery Web ServiceSinatra and JSONQuery Web Service
Sinatra and JSONQuery Web Service
 
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
RESTful API を Chalice で紐解く 〜 Python Serverless Microframework for AWS 〜
 
Sinatra
SinatraSinatra
Sinatra
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
fog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloudfog or: How I Learned to Stop Worrying and Love the Cloud
fog or: How I Learned to Stop Worrying and Love the Cloud
 
Socket applications
Socket applicationsSocket applications
Socket applications
 
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
fog or: How I Learned to Stop Worrying and Love the Cloud (OpenStack Edition)
 
8 Minutes On Rack
8 Minutes On Rack8 Minutes On Rack
8 Minutes On Rack
 
Intro to Rack
Intro to RackIntro to Rack
Intro to Rack
 
Crossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end FrameworkCrossing the Bridge: Connecting Rails and your Front-end Framework
Crossing the Bridge: Connecting Rails and your Front-end Framework
 
Wider than rails
Wider than railsWider than rails
Wider than rails
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!Rapid Prototyping FTW!!!
Rapid Prototyping FTW!!!
 
infra-as-code
infra-as-codeinfra-as-code
infra-as-code
 
Building web framework with Rack
Building web framework with RackBuilding web framework with Rack
Building web framework with Rack
 
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine YardHow I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
How I Learned to Stop Worrying and Love the Cloud - Wesley Beary, Engine Yard
 
Build Web Apps using Node.js
Build Web Apps using Node.jsBuild Web Apps using Node.js
Build Web Apps using Node.js
 

More from LaunchAny

Refining Your API Design - Architecture and Modeling Learning Event
Refining Your API Design - Architecture and Modeling Learning EventRefining Your API Design - Architecture and Modeling Learning Event
Refining Your API Design - Architecture and Modeling Learning Event
LaunchAny
 
Event-Based API Patterns and Practices
Event-Based API Patterns and PracticesEvent-Based API Patterns and Practices
Event-Based API Patterns and Practices
LaunchAny
 
Event-based API Patterns and Practices - AsyncAPI Online Conference
Event-based API Patterns and Practices - AsyncAPI Online ConferenceEvent-based API Patterns and Practices - AsyncAPI Online Conference
Event-based API Patterns and Practices - AsyncAPI Online Conference
LaunchAny
 
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and StreamingGlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
LaunchAny
 
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
LaunchAny
 
APIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
APIStrat Keynote: Lessons in Transforming the Enterprise to an API PlatformAPIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
APIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
LaunchAny
 
Austin API Summit 2018: Are REST APIs Still Relevant Today?
Austin API Summit 2018: Are REST APIs Still Relevant Today?Austin API Summit 2018: Are REST APIs Still Relevant Today?
Austin API Summit 2018: Are REST APIs Still Relevant Today?
LaunchAny
 
GlueCon 2018: Are REST APIs Still Relevant Today?
GlueCon 2018: Are REST APIs Still Relevant Today?GlueCon 2018: Are REST APIs Still Relevant Today?
GlueCon 2018: Are REST APIs Still Relevant Today?
LaunchAny
 
Lessons in Transforming the Enterprise to an API Platform
Lessons in Transforming the Enterprise to an API PlatformLessons in Transforming the Enterprise to an API Platform
Lessons in Transforming the Enterprise to an API Platform
LaunchAny
 
APIStrat 2017: API Design in the Age of Bots, IoT, and Voice
APIStrat 2017: API Design in the Age of Bots, IoT, and VoiceAPIStrat 2017: API Design in the Age of Bots, IoT, and Voice
APIStrat 2017: API Design in the Age of Bots, IoT, and Voice
LaunchAny
 
API Design in the Age of Bots, IoT, and Voice
API Design in the Age of Bots, IoT, and VoiceAPI Design in the Age of Bots, IoT, and Voice
API Design in the Age of Bots, IoT, and Voice
LaunchAny
 
APIStrat 2016: Moving Toward a Modular Enterprise
APIStrat 2016: Moving Toward a Modular EnterpriseAPIStrat 2016: Moving Toward a Modular Enterprise
APIStrat 2016: Moving Toward a Modular Enterprise
LaunchAny
 
API:World 2016 - Applying Domain Driven Design to APIs and Microservices
API:World 2016 - Applying Domain Driven Design to APIs and MicroservicesAPI:World 2016 - Applying Domain Driven Design to APIs and Microservices
API:World 2016 - Applying Domain Driven Design to APIs and Microservices
LaunchAny
 
Moving Toward a Modular Enterprise - All About the API Conference 2016
Moving Toward a Modular Enterprise - All About the API Conference 2016Moving Toward a Modular Enterprise - All About the API Conference 2016
Moving Toward a Modular Enterprise - All About the API Conference 2016
LaunchAny
 
Designing APIs and Microservices Using Domain-Driven Design
Designing APIs and Microservices Using Domain-Driven DesignDesigning APIs and Microservices Using Domain-Driven Design
Designing APIs and Microservices Using Domain-Driven Design
LaunchAny
 
Applying Domain-Driven Design to APIs and Microservices - Austin API Meetup
Applying Domain-Driven Design to APIs and Microservices  - Austin API MeetupApplying Domain-Driven Design to APIs and Microservices  - Austin API Meetup
Applying Domain-Driven Design to APIs and Microservices - Austin API Meetup
LaunchAny
 
APIs Are Forever - How to Design Long-Lasting APIs
APIs Are Forever - How to Design Long-Lasting APIsAPIs Are Forever - How to Design Long-Lasting APIs
APIs Are Forever - How to Design Long-Lasting APIs
LaunchAny
 
API Thinking - How to Design APIs Through Systems Design
API Thinking - How to Design APIs Through Systems DesignAPI Thinking - How to Design APIs Through Systems Design
API Thinking - How to Design APIs Through Systems Design
LaunchAny
 
Swagger 2.0: Latest and Greatest
Swagger 2.0: Latest and GreatestSwagger 2.0: Latest and Greatest
Swagger 2.0: Latest and Greatest
LaunchAny
 
Gluecon 2015 Recap
Gluecon 2015 RecapGluecon 2015 Recap
Gluecon 2015 Recap
LaunchAny
 

More from LaunchAny (20)

Refining Your API Design - Architecture and Modeling Learning Event
Refining Your API Design - Architecture and Modeling Learning EventRefining Your API Design - Architecture and Modeling Learning Event
Refining Your API Design - Architecture and Modeling Learning Event
 
Event-Based API Patterns and Practices
Event-Based API Patterns and PracticesEvent-Based API Patterns and Practices
Event-Based API Patterns and Practices
 
Event-based API Patterns and Practices - AsyncAPI Online Conference
Event-based API Patterns and Practices - AsyncAPI Online ConferenceEvent-based API Patterns and Practices - AsyncAPI Online Conference
Event-based API Patterns and Practices - AsyncAPI Online Conference
 
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and StreamingGlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
GlueCon 2019: Beyond REST - Moving to Event-Based APIs and Streaming
 
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
Austin API Summit 2019 - APIs, Microservices, and Serverless: The Shape of Th...
 
APIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
APIStrat Keynote: Lessons in Transforming the Enterprise to an API PlatformAPIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
APIStrat Keynote: Lessons in Transforming the Enterprise to an API Platform
 
Austin API Summit 2018: Are REST APIs Still Relevant Today?
Austin API Summit 2018: Are REST APIs Still Relevant Today?Austin API Summit 2018: Are REST APIs Still Relevant Today?
Austin API Summit 2018: Are REST APIs Still Relevant Today?
 
GlueCon 2018: Are REST APIs Still Relevant Today?
GlueCon 2018: Are REST APIs Still Relevant Today?GlueCon 2018: Are REST APIs Still Relevant Today?
GlueCon 2018: Are REST APIs Still Relevant Today?
 
Lessons in Transforming the Enterprise to an API Platform
Lessons in Transforming the Enterprise to an API PlatformLessons in Transforming the Enterprise to an API Platform
Lessons in Transforming the Enterprise to an API Platform
 
APIStrat 2017: API Design in the Age of Bots, IoT, and Voice
APIStrat 2017: API Design in the Age of Bots, IoT, and VoiceAPIStrat 2017: API Design in the Age of Bots, IoT, and Voice
APIStrat 2017: API Design in the Age of Bots, IoT, and Voice
 
API Design in the Age of Bots, IoT, and Voice
API Design in the Age of Bots, IoT, and VoiceAPI Design in the Age of Bots, IoT, and Voice
API Design in the Age of Bots, IoT, and Voice
 
APIStrat 2016: Moving Toward a Modular Enterprise
APIStrat 2016: Moving Toward a Modular EnterpriseAPIStrat 2016: Moving Toward a Modular Enterprise
APIStrat 2016: Moving Toward a Modular Enterprise
 
API:World 2016 - Applying Domain Driven Design to APIs and Microservices
API:World 2016 - Applying Domain Driven Design to APIs and MicroservicesAPI:World 2016 - Applying Domain Driven Design to APIs and Microservices
API:World 2016 - Applying Domain Driven Design to APIs and Microservices
 
Moving Toward a Modular Enterprise - All About the API Conference 2016
Moving Toward a Modular Enterprise - All About the API Conference 2016Moving Toward a Modular Enterprise - All About the API Conference 2016
Moving Toward a Modular Enterprise - All About the API Conference 2016
 
Designing APIs and Microservices Using Domain-Driven Design
Designing APIs and Microservices Using Domain-Driven DesignDesigning APIs and Microservices Using Domain-Driven Design
Designing APIs and Microservices Using Domain-Driven Design
 
Applying Domain-Driven Design to APIs and Microservices - Austin API Meetup
Applying Domain-Driven Design to APIs and Microservices  - Austin API MeetupApplying Domain-Driven Design to APIs and Microservices  - Austin API Meetup
Applying Domain-Driven Design to APIs and Microservices - Austin API Meetup
 
APIs Are Forever - How to Design Long-Lasting APIs
APIs Are Forever - How to Design Long-Lasting APIsAPIs Are Forever - How to Design Long-Lasting APIs
APIs Are Forever - How to Design Long-Lasting APIs
 
API Thinking - How to Design APIs Through Systems Design
API Thinking - How to Design APIs Through Systems DesignAPI Thinking - How to Design APIs Through Systems Design
API Thinking - How to Design APIs Through Systems Design
 
Swagger 2.0: Latest and Greatest
Swagger 2.0: Latest and GreatestSwagger 2.0: Latest and Greatest
Swagger 2.0: Latest and Greatest
 
Gluecon 2015 Recap
Gluecon 2015 RecapGluecon 2015 Recap
Gluecon 2015 Recap
 

Recently uploaded

OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
OpenMetadata
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
lorraineandreiamcidl
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Undress Baby
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
Neo4j
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Crescat
 

Recently uploaded (20)

OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024OpenMetadata Community Meeting - 5th June 2024
OpenMetadata Community Meeting - 5th June 2024
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdfRevolutionizing Visual Effects Mastering AI Face Swaps.pdf
Revolutionizing Visual Effects Mastering AI Face Swaps.pdf
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 
Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
GraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph TechnologyGraphSummit Paris - The art of the possible with Graph Technology
GraphSummit Paris - The art of the possible with Graph Technology
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
Introducing Crescat - Event Management Software for Venues, Festivals and Eve...
 

Using Sinatra to Build REST APIs in Ruby

  • 1. Using  Sinatra  to  Build   REST  APIs  in  Ruby   James  Higginbotham   API  Architect   @launchany  
  • 4. Sinatra  is  a  DSL  for  quickly   crea<ng  web  applica<ons  in   Ruby  
  • 5. # hi.rb require 'rubygems’ require 'sinatra' get '/' do 'Hello world!’ end $ gem install sinatra $ ruby hi.rb == Sinatra has taken the stage ... >> Listening on 0.0.0.0:4567 $ curl http://0.0.0.0:4567 Hello World
  • 6. HOW  DOES  SINATRA  WORK?  
  • 7. Rou?ng:  Verb  +  PaCern  +  Block   post ’/' do .. block .. end
  • 8. Rou?ng:  Named  Params   get '/:id' do model = MyModel.find( params[:id] ) ... end
  • 9. Rou?ng:  Splat  Support   get '/say/*/to/*' do # matches /say/hello/to/world params['splat'] # => ["hello", "world"] ... end get '/download/*.*' do # matches /download/path/to/file.xml params['splat'] # => ["path/to/file", "xml"] ... end
  • 10. Rou?ng:  Regex  Support   get /A/hello/([w]+)z/ do "Hello, #{params['captures'].first}!” ... end
  • 11. Rou?ng:  Op?onal  Parameters   get '/posts.?:format?' do # matches "GET /posts" and # any extension "GET /posts.rss", "GET /posts.xml" etc. end
  • 12. Rou?ng:  URL  Query  Parameters   get '/posts' do # matches "GET /posts?title=foo&author=bar" title = params['title'] author = params['author'] # uses title and author variables; # query is optional to the /posts route End
  • 13. Rou?ng:  Condi?onal  Matching   get '/', :host_name => /^admin./ do "Admin Area, Access denied!" end get '/', :provides => 'html' do haml :index end get '/', :provides => ['rss', 'atom', 'xml'] do builder :feed end
  • 14. Rou?ng:  Custom  Condi?ons   set(:probability) { |value| condition { rand <= value } } get '/win_a_car', :probability => 0.1 do "You won!" end get '/win_a_car' do "Sorry, you lost." End
  • 15. Returning  Results   # 1. String containing the body and default code of 200 get '/' do 'Hello world!’ end # 2. Response code + body get '/' do [200, 'Hello world!’] end # 3. Response code + headers + body get '/' do [200, {'Content-Type' => 'text/plain'}, 'Hello world!’] end
  • 17. Hello  World  with  Rack   # hello_world.rb require 'rack' require 'rack/server’ class HelloWorldApp def self.call(env) [200, {}, 'Hello World’] end end Rack::Server.start :app => HelloWorldApp
  • 18. Rack  env   # hello_world.rb require 'rack' require 'rack/server’ class HelloWorldApp def self.call(env) [200, {}, "Hello World. You said: #{env['QUERY_STRING']}"] end end Rack::Server.start :app => HelloWorldApp
  • 19. Typical  env   { "SERVER_SOFTWARE"=>"thin 1.4.1 codename Chromeo", "SERVER_NAME"=>"localhost", "rack.input"=>#<StringIO:0x007fa1bce039f8>, "rack.version"=>[1, 0], "rack.errors"=>#<IO:<STDERR>>, "rack.multithread"=>false, "rack.multiprocess"=>false, "rack.run_once"=>false, "REQUEST_METHOD"=>"GET", "REQUEST_PATH"=>"/favicon.ico", "PATH_INFO"=>"/favicon.ico", "REQUEST_URI"=>"/favicon.ico", "HTTP_VERSION"=>"HTTP/1.1", "HTTP_HOST"=>"localhost:8080", "HTTP_CONNECTION"=>"keep-alive", "HTTP_ACCEPT"=>"*/*”, ...
  • 20. Typical  env  (con’t)   ... "HTTP_USER_AGENT"=> "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11", "HTTP_ACCEPT_ENCODING"=>"gzip,deflate,sdch", "HTTP_ACCEPT_LANGUAGE"=>"en-US,en;q=0.8", "HTTP_ACCEPT_CHARSET"=>"ISO-8859-1,utf-8;q=0.7,*;q=0.3", "HTTP_COOKIE"=> "_gauges_unique_year=1; _gauges_unique_month=1", "GATEWAY_INTERFACE"=>"CGI/1.2", "SERVER_PORT"=>"8080", "QUERY_STRING"=>"", "SERVER_PROTOCOL"=>"HTTP/1.1", "rack.url_scheme"=>"http", "SCRIPT_NAME"=>"", "REMOTE_ADDR"=>"127.0.0.1", ... }
  • 21. The  Rack::Request  Wrapper   class HelloWorldApp def self.call(env) request = Rack::Request.new(env) request.params # contains the union of GET and POST params request.xhr? # requested with AJAX require.body # the incoming request IO stream if request.params['message'] [200, {}, request.params['message']] else [200, {}, 'Say something to me!'] end end end
  • 22. Rack  Middleware   u  Rack  allows  for  chaining  mul?ple  call()   methods   u  We  can  do  anything  we  want  within  each  call()   u  This  includes  separa?ng  behavior  into   reusable  classes  (e.g.  across  Sinatra  and  Rails)   u  SRP  (Single  Responsibility  Principle)   – Each  class  has  a  single  responsibility   – Our  app  is  composed  of  mul?ple  classes  that  each   do  one  thing  well  
  • 23. Rack::Builder  for  Middleware   # this returns an app that responds to call cascading down # the list of middlewares. app = Rack::Builder.new do use Rack::Etag # Add an ETag use Rack::ConditionalGet # Support Caching use Rack::Deflator # GZip run HelloWorldApp # Say Hello end Rack::Server.start :app => app # Resulting call tree: # Rack::Etag # Rack::ConditionalGet # Rack::Deflator # HelloWorldApp
  • 24. Using  the  Rackup  Command   u  Combines  all  of  these  concepts  into  a  config   u  Will  start  a  web  process  with  your  Rack  app   u  Central  loca?on  for  requires,  bootstrapping   u  Enables  middleware  to  be  configured  as  well   u  Default  filename  is  config.ru   u  Used  to  bootstrap  Rails  
  • 25. Using  Rackup   # config.ru # HelloWorldApp defintion # EnsureJsonResponse defintion # Timer definition use Timer use EnsureJsonResponse run HelloWorldApp $ rackup –p 4567
  • 26. Using  Mul?ple  Sinatra  Apps   u  Rackup  allows  for  moun?ng  mul?ple  Sinatra   Apps   u  This  allows  for  more  modular  APIs   u  Recommend  one  Sinatra  app  per  top-­‐level   resource  
  • 27. Moun?ng  Mul?ple  Sinatra  Apps   # config.ru require 'sinatra' require 'app/auth_api' require 'app/users_api' require 'app/organizations_api' map "/auth" do run AuthApi end map "/users" do run UsersApi end map "/organizations" do run OrganizationsApi end
  • 28. Important:  Require  !=  Automa?c   u  Must  manage  your  own  requires   u  No  free  ride  (like  with  Rails)   u  This  means  order  of  requires  is  important!  
  • 29. WHAT  IS  A  REST  API?  
  • 30. Mul?ple  API  Design  Choices   u  RPC-­‐based   – Uses  HTTP  for  transport  only   – Endpoints  are  not  unique,  only  the  payload   – No  HTTP  caching  available   – e.g.  POST  /getUserDetails,  POST  /createUser   u  Resource-­‐based   – Unique  URLs  for  resources  and  collec?ons   – HTTP  caching  available   – e.g.  GET  /users/{userId}  and  GET  /users  
  • 31. Hypermedia  REST   u  An  architectural  style,  with  constraints   u  A  set  of  constraints,  usually  on  top  of  HTTP   u  Not  a  standard;  builds  on  the  standard  of   HTTP   u  Mul?ple  content  types  (e.g.  JSON,  XML,  CSV)   u  The  response  is  a  representa?on  of  the   resource  state  (data)  plus  server-­‐side  state  in   the  form  of  ac<ons/transi<ons  (links)  
  • 32. BUILDING  AN  API  USING  SINATRA  
  • 33. Resource  Lifecycle  using  Sinatra   get '/users' do .. list a resource collection (and search) .. end get '/users/:id' do .. resource instance details .. end post '/users' do .. create new resource .. end put '/users/:id' do .. replace resource .. End delete ’/users/:id' do .. annihilate resource .. end
  • 34. List  Resources  Example   get '/users' do # 1. capture any search filters using params[] email_filter = params[:email] # 2. build query and fetch results from database if email_filter users = User.where( email: email_filter ).all else users = User.all # 3. marshal results to proper content type (e.g. JSON) [200, users.to_json] end
  • 35. List  Resources  Example   get '/users' do # 1. capture any search filters using params[] email_filter = params[:email] # 2. build query and fetch results from database if email_filter users = User.where( email: email_filter ).all else users = User.all # 3. marshal results to proper content type (e.g. JSON) [200, users.to_json] # Q: Which ORM should we use with Sinatra? # Q: Can we customize the results format easily? end
  • 37. Selec?ng  an  ORM   u  Ac?veRecord   u  DataMapper   u  Sequel  (my  favorite)   – Flexible  as  it  supports  Datasets  and  Models  
  • 38. Sequel  Datasets  Example   require 'sequel' DB = Sequel.sqlite # memory database DB.create_table :items do primary_key :id String :name Float :price end items = DB[:items] # Create a dataset items.insert(:name => 'abc', :price => rand * 100) items.insert(:name => 'def', :price => rand * 100) items.insert(:name => 'ghi', :price => rand * 100) puts "Item count: #{items.count}" puts "The average price is: #{items.avg(:price)}”
  • 39. Sequel  Model  Example   require 'sequel' DB = Sequel.sqlite # memory database class Post < Sequel::Model end post = Post[123] post = Post.new post.title = 'hello world' post.save
  • 40. Select  a  Marshaling  Library   u  Ac?veModel::Serializers  (AMS)     – Works  with  Kaminari  and  WillPaginate   – Supported  by  Rails  core  team   – One-­‐way  JSON  genera?on  only   u  Roar+Representable  (my  favorite)   – Works  with  and  without  Rails   – Bi-­‐direc?onal  marshaling   – Supports  JSON,  XML,  YAML,  hash  
  • 41. Representable   module SongRepresenter include Representable::JSON property :title property :track collection :composers end class Song < OpenStruct end song = Song.new(title: "Fallout", track: 1) song.extend(SongRepresenter).to_json > {"title":"Fallout","track":1} song = Song.new.extend(SongRepresenter).from_json(% { {"title":"Roxanne"} }) > #<Song title="Roxanne">
  • 42. Roar  +  Representable   module SongRepresenter include Roar::JSON include Roar::Hypermedia property :title property :track collection :composers link :self do "/songs/#{title}" end end song = Song.new(title: "Fallout", track: 1) song.extend(SongRepresenter).to_json > {"title":"Fallout","track":1,"links": [{"rel":"self","href":"/songs/Fallout"}]}"
  • 43. Tools  for  Tes?ng  Your  API   u  Unit  –  RSpec   – Models,  helpers   u  Integra?on  –  RSpec   – Make  HTTP  calls  to  a  running  Sinatra  process   – Controller-­‐focused   u  Acceptance/BDD  –  RSpec,  Cucumber   – Make  HTTP  calls  to  a  running  Sinatra  process   – Use-­‐case/story  focused  
  • 45. Addi?onal  Gems   u  faraday  –  HTTP  client  with  middleware  for   tes?ng  and  3rd  party  API  integra?on   u  xml-­‐simple  –  Easy  XML  parsing  and  genera?on   u  faker  –  Generates  fake  names,  addresses,  etc.   u  uuidtools  –  uuid  generator  when  incremen?ng   integers  aren’t  good  enough   u  bcrypt  –  Ruby  binding  for  OpenBSD  hashing   algorithm,  to  secure  data  at  rest  
  • 46. Addi?onal  Gems  (part  2)   u  rack-­‐conneg  –  Content  nego?a?on  support   get '/hello' do response = { :message => 'Hello, World!' } respond_to do |wants| wants.json { response.to_json } wants.xml { response.to_xml } wants.other { content_type 'text/plain' error 406, "Not Acceptable" } end end curl -H "Accept: application/json" http://localhost:4567/ hello
  • 47. Addi?onal  Gems  (part  3)   u  hirb  –  Console  formaing  of  data  from  CLI,   Rake  tasks   irb>> Tag.last +-----+-------------------------+-------------+ | id | created_at | description | +-----+-------------------------+-------------+ | 907 | 2009-03-06 21:10:41 UTC | blah | +-----+-------------------------+-------------+ 1 row in set
  • 48. Reloading  with  Shotgun  Gem   u  No  automa?c  reload  of  classes  with  Sinatra   u  Instead,  use  the  shotgun  gem:   u  Note:  Only  works  with  Ruby  MRI  where  fork()   is  available  (POSIX)   $ gem install shotgun $ shotgun config.ru
  • 49. Puma  +  JRuby   u  Ruby  MRI  is  geing  beCer   u  JVM  is  faster  (2-­‐5x),  very  mature  (since  1997)   u  High  performance  garbage  collectors,  na?ve   threading,  JMX  management  extensions   u  JDBC  libraries  very  mature  and  performant  for   SQL-­‐based  access   u  Puma  is  recommended  over  unicorn  for  JRuby    
  • 50. From  Sinatra  to  Padrino   u  Padrino  provides  Rails-­‐like  environment  for   Sinatra   u  Build  in  Sinatra,  move  to  Padrino  when   needed   u  Generators,  pluggable  modules,  admin   generator  
  • 51. Resources   u  Sinatra  Docs:     hCp://www.sinatrarb.com/intro.html     u  Introduc?on  to  Rack:   hCp://hawkins.io/2012/07/rack_from_the_beginning/     u  Sequel  Gem:   hCps://github.com/jeremyevans/sequel     u  Roar/Representable:   hCps://github.com/apotonick/roar     hCps://github.com/apotonick/representable    
  • 52. Thanks  Ya’ll   James  Higginbotham   james@launchany.com   hCp://launchany.com     @launchany     Design  Beau?ful  APIs:   hCp://TheApiDesignBook.com