The document discusses designing APIs with Ruby. It covers what an API is, different types of APIs, REST and CRUD conventions, implementing APIs with Ruby on Rails, versioning APIs, common response codes, and using the Rabl gem to generate API views. The presentation provides guidance on building APIs that are easy to implement, maintain and scale, with a focus on RESTful design principles and best practices for API development.
17. RECURSO
Cualquier cosa expuesta mediante web
Tienen una representación en datos
Con un servicio web intercambiamos
representaciones de recursos
Friday, June 15, 2012
26. ¿PORQUÉ UN API?
Aumenta la flexibilidad de un servicio
Friday, June 15, 2012
27. ¿PORQUÉ UN API?
Aumenta la flexibilidad de un servicio
Aumenta la utilidad de un servicio
Friday, June 15, 2012
28. ¿PORQUÉ UN API?
Aumenta la flexibilidad de un servicio
Aumenta la utilidad de un servicio
Libera los datos de usuario
Friday, June 15, 2012
29. ¿PORQUÉ UN API?
Aumenta la flexibilidad de un servicio
Aumenta la utilidad de un servicio
Libera los datos de usuario
Proporciona valor de negocio
Friday, June 15, 2012
46. VERSIONANDO TU API
• API Interna (entre aplicaciones)
• API Externa (aplicacion movil ? )
• API Usuarios (publico en general)
Friday, June 15, 2012
47. VERSIONANDO TU API
/int/api/products
/ext/api/products
/pub/api/products
Friday, June 15, 2012
48. VERSIONANDO TU API
/int/api/products?version=2
/ext/api/products?version=2
/pub/api/products?version=2
Friday, June 15, 2012
49. VERSIONANDO TU API
/v2/int/api/products
/v2/ext/api/products
/v2/pub/api/products
Friday, June 15, 2012
52. MUNDO IDEAL
Uso de: Accept Header
Accept: application/vnd.mycompany.com;version=2,application/json
Friday, June 15, 2012
53. CODIGOS HTTP
200 OK
201 Created
202 Accepted
400 Bad Request
401 Unauthorized
402 Payment Required
404 Not Found
409 Conflict
422 Unprocessable Entity
500 Internal Server Error
503 Service Unavailable
Friday, June 15, 2012
54. CODIGOS HTTP
HTTP/1.1 401 Unauthorized
{
“errors”: [
“api_key not found”
]
}
Friday, June 15, 2012
55. CODIGOS HTTP
HTTP/1.1 401 Unauthorized
{
“errors”: [
“api_key no valida”,
“api_key no puede contener
espacios”
]
}
Friday, June 15, 2012
56. CODIGOS HTTP
HTTP/1.1 401 Unauthorized
{
“errors”: [
“api_key no encontrada, por favor
visita http://account.myapp.com/api para
obtenerla”
]
}
Friday, June 15, 2012
57. CODIGOS HTTP
HTTP/1.1 400 Bad Request
{
“errors”: [
“Estructura JSON no valida”,
“unexpected TSTRING, expected ‘}’ at
line 2”
]
}
Friday, June 15, 2012
58. DOCUMENTACION
HTTP/1.1 422 Unprocessable Entity
{
“errors”: [
“vendor_code: no puede estar vacio”
],
“documentacion”: [
“vendor_code”: [
“descripcion” : “Codigo asignado por proveedor”,
“formato” : “Combinacion de tres letras seguidas de 4
numeros”,
“ejemplo” : “SOL1234”
]
]
}
Friday, June 15, 2012
59. CODIGOS HTTP
HTTP/1.1 503 Service Unavailable
{
“messages”: [
“En mantenimiento”
]
}
Friday, June 15, 2012
60. OPCIONES AVANZADAS
• Simuladores
• Autenticación
• Validadores
• Limite de uso
• Rapidez
• Balanceo
Friday, June 15, 2012
61. USANDO RUBY ON
RAILS PARA
IMLEMENTAR UNA API
Friday, June 15, 2012
62. APIS ON RAILS - REST
MyApp::Application.routes.draw do
resources :products
end
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
Friday, June 15, 2012
63. APIS ON RAILS - REST
MyApp::Application.routes.draw do
scope ‘/api’ do
resources :products
end
end
products GET /api/products(.:format) products#index
POST /api/products(.:format) products#create
new_product GET /api/products/new(.:format) products#new
edit_product GET /api/products/:id/edit(.:format) products#edit
product GET /api/products/:id(.:format) products#show
PUT /api/products/:id(.:format) products#update
DELETE /api/products/:id(.:format) products#destroy
Friday, June 15, 2012
64. APIS ON RAILS -
gem 'versionist'
VERSIONES
MyApp::Application.routes.draw do
api_version(:module => 'V1', :path => 'v2') do
resources :products
end
end
v2_products GET /v2/products(.:format) V1/products#index
POST /v2/products(.:format) V1/products#create
new_v2_product GET /v2/products/new(.:format) V1/products#new
edit_v2_product GET /v2/products/:id/edit(.:format) V1/products#edit
v2_product GET /v2/products/:id(.:format) V1/products#show
PUT /v2/products/:id(.:format) V1/products#update
DELETE /v2/products/:id(.:format) V1/products#destroy
Friday, June 15, 2012
65. APIS ON RAILS,
CONTROLADOR
class V2::ProductsController < ApplicationController
respond_to :json
def index
@products = V2::Product.paginate(:page => (params[:page] || 1),
:per_page => (params[:per_page] || 100)).all
respond_with @products
end
def show
@product = V2::Product.find(params[:id])
respond_with @product
end
def update
@product = V2::Product.find(params[:id])
@product.update_attributes(params[:product])
respond_with @product
end
def destroy
@product = V2::Product.find(params[:id])
respond_with @product.destroy
end
end
Friday, June 15, 2012
66. APIS ON RAILS -
MODELO
class V2::Product < Product
JSON_ATTRIBUTES = {
properties: [
:id,
:upc,
:sku,
:list_cost,
:color,
:dimension,
:size,
:created_at,
:updated_at,
],
methods: [
:units_on_hand
]
}
end
Friday, June 15, 2012
67. APIS ON RAILS,
CONTROLADOR
gem ‘rabl’
class V3::ProductsController < ApplicationController
respond_to :json, :xml
def index
@products = V3::Product.paginate(:page => (params[:page] || 1),
:per_page => (params[:per_page] || 100)).all
end
def show
@product = V3::Product.find(params[:id])
end
def update
@product = V3::Product.find(params[:id])
@product.update_attributes(params[:product])
end
def destroy
@product = V3::Product.find(params[:id])
render json: {}, status: @product.destroy ? :ok : :unprocessable_entity
end
end
Friday, June 15, 2012
69. APIS ON RAILS
VISTAS
gem ‘jbuilder’
Jbuilder.encode do |json|
json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)
json.author do |json|
json.name @message.creator.name.familiar
json.email_address @message.creator.email_address_with_name
json.url url_for(@message.creator, format: :json)
end
if current_user.admin?
json.visitors calculate_visitors(@message)
end
json.comments @message.comments, :content, :created_at
end
Friday, June 15, 2012
70. APIS ON RAILS
VISTAS
gem ‘active_model_serializer’
class PostSerializer < ActiveModel::Serializer
attributes :id, :body
attribute :title, :key => :name
has_many :comments
def tags
tags.order :name
end
end
Friday, June 15, 2012
71. APIS ON RAILS
SEGURIDAD
Devise
Autenticacion Flexible para aplicaciones Rails
Compuesta de 12 modulos: database authenticable,
token authenticable, omniauthable, confirmable,
recoverable, registerable, trackable, timeoutable,
validatable, lockable
Friday, June 15, 2012
72. APIS ON RAILS
SEGURIDAD
Devise
Autenticacion Flexible para aplicaciones Rails
Compuesta de 12 modulos: database authenticable,
token authenticable, omniauthable, confirmable,
recoverable, registerable, trackable, timeoutable,
validatable, lockable
Friday, June 15, 2012
73. APIS ON RAILS
SEGURIDAD
gem ‘rabl’
class V3::ProductsController < ApplicationController
before_filter :authenticate_user!
respond_to :json, :xml
def index
@products = V3::Product.paginate(:page => (params[:page] || 1),
:per_page => (params[:per_page] || 100)).all
end
def show
@product = V3::Product.find(params[:id])
end
def update
@product = V3::Product.find(params[:id])
@product.update_attributes(params[:product])
end
def destroy
@product = V3::Product.find(params[:id])
render json: {}, status: @product.destroy ? :ok : :unprocessable_entity
end
end
Friday, June 15, 2012
74. APIS ON RAILS
PRUEBAS
describe V3::ProductsController do
before do
@request.env["HTTP_ACCEPT"] = "application/json"
end
describe "#index" do
context "cuando no se pasa ningun atributo" do
it "regresa los registros en paginas" do
get :index
response.should be_success
data = JSON.parse(response.body)
Product.count.should > 0
data['products'].length.should == Product.count
end
end
end
end
Friday, June 15, 2012
75. APIS ON RAILS
PRUEBAS
describe V3::ProductsController do
before do
@request.env["HTTP_ACCEPT"] = "application/json"
end
describe "#show" do
context "pasando un id inexistente" do
it "responde con http 404 y un mensaje de error" do
get :show, id: -1
response.code.should == "404"
JSON.parse(response.body)['error'].should == "ActiveRecord::RecordNotFound"
JSON.parse(response.body)['message'].should == "Couldn't find Product with
id=-1"
end
end
end
end
Friday, June 15, 2012
76. APIS ON RAILS
PRUEBAS
describe V3::ProductsController do
before do
@request.env["HTTP_ACCEPT"] = "application/json"
end
describe "#create" do
context "con malos atributos" do
it "responde con un error" do
post :create, product: {bad_key: "foo"}
response.code.should == "400"
json_response = JSON.parse(response.body)
json_response['error'].should == "ActiveRecord::UnknownAttributeError"
json_response['message'].should == "unknown attribute: bad_key"
end
end
end
end
Friday, June 15, 2012
77. APIS ON RAILS
PRUEBAS
describe V3::ProductsController do
before do
@request.env["HTTP_ACCEPT"] = "application/json"
end
describe "#create" do
context "con atributos correctos" do
it "responde correctamente y crea el producto" do
expect {
post :create, product: {name: "productito"}
}.to change(Product, :count).by(1)
end
end
end
end
Friday, June 15, 2012
84. use ActionDispatch::Static
use Rack::Lock
use
#<ActiveSupport::Cache::Strategy::Loc
alCache::Middleware:0x007fd3b32928c0>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActionDispatch::Cookies
use
ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use
ActionDispatch::BestStandardsSupport
use
Rack::Mongoid::Middleware::IdentityMa
p
Friday, June 15, 2012
85. use ActionDispatch::Static
use Rack::Lock
use
#<ActiveSupport::Cache::Strategy::Loc use ActionDispatch::Static
alCache::Middleware:0x007fd3b32928c0> use Rack::Lock
use Rack::Runtime use
use Rack::MethodOverride #<ActiveSupport::Cache::Strategy::LocalCac
use ActionDispatch::RequestId he::Middleware:0x007fe74448cf50>
use Rails::Rack::Logger use Rack::Runtime
use ActionDispatch::ShowExceptions use ActionDispatch::RequestId
use ActionDispatch::DebugExceptions use Rails::Rack::Logger
use ActionDispatch::RemoteIp use ActionDispatch::ShowExceptions
use ActionDispatch::Reloader use ActionDispatch::DebugExceptions
use ActionDispatch::Callbacks use ActionDispatch::RemoteIp
use ActionDispatch::Cookies use ActionDispatch::Reloader
use use ActionDispatch::Callbacks
ActionDispatch::Session::CookieStore use
use ActionDispatch::Flash ActiveRecord::ConnectionAdapters::Connecti
use ActionDispatch::ParamsParser onManagement
use ActionDispatch::Head use ActiveRecord::QueryCache
use Rack::ConditionalGet use ActionDispatch::ParamsParser
use Rack::ETag use ActionDispatch::Head
use use Rack::ConditionalGet
ActionDispatch::BestStandardsSupport use Rack::ETag
use
Rack::Mongoid::Middleware::IdentityMa
p
Friday, June 15, 2012