SlideShare a Scribd company logo
Diseño de APIs con Ruby
                           Edwin Cruz @softr8


                                                #SGRuby


Friday, June 15, 2012
PLAN

    • Que               es una API

    • Como               implementar una buena API

    • Usando              Ruby on Rails para implementar una API

    • Patrones             de diseño




Friday, June 15, 2012
“               Application
                        Programming
                        Interface


                                      “
Friday, June 15, 2012
API

                 Es una manera para comunicar
                  dos aplicaciones entre ellas.




Friday, June 15, 2012
TIPOS DE API


    • Library

    • SDK

    • Web               services




Friday, June 15, 2012
PRIMERAS API - SOAP

                        Simple
                        Object
                        Access
                        Protocol




Friday, June 15, 2012
REST

                        REpresentation
                        State
                        Transfer




Friday, June 15, 2012
CRUD

                        Create   Altas
                        Read     Bajas
                        Update   Cambios
                        Delete   Consultas




Friday, June 15, 2012
REST ⋍ CRUD




Friday, June 15, 2012
REST ⋍ CRUD



                        Recursos a través de URI
                         Uso de verbos HTTP




Friday, June 15, 2012
REST-ISH + JSON




Friday, June 15, 2012
REST-ISH + JSON


                               =




Friday, June 15, 2012
REST-ISH + JSON


                                   =
                            Cosas Increibles




Friday, June 15, 2012
RECURSO




Friday, June 15, 2012
RECURSO

Cualquier cosa expuesta mediante web




Friday, June 15, 2012
RECURSO

Cualquier cosa expuesta mediante web
Tienen una representación en datos




Friday, June 15, 2012
RECURSO

Cualquier cosa expuesta mediante web
Tienen una representación en datos
Con un servicio web intercambiamos
representaciones de recursos



Friday, June 15, 2012
REQUISITOS REST




Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades




Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades
Cliente/Servidor




Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades
Cliente/Servidor
Sin estado




Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades
Cliente/Servidor
Sin estado
“Cacheable”




Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades
Cliente/Servidor
Sin estado
“Cacheable”
Sistema a capas



Friday, June 15, 2012
REQUISITOS REST
Separación de responsabilidades
Cliente/Servidor
Sin estado
“Cacheable”
Sistema a capas
Interface uniforme


Friday, June 15, 2012
¿PORQUÉ UN API?




Friday, June 15, 2012
¿PORQUÉ UN API?

                    Aumenta la flexibilidad de un servicio




Friday, June 15, 2012
¿PORQUÉ UN API?

                    Aumenta la flexibilidad de un servicio
                     Aumenta la utilidad de un servicio




Friday, June 15, 2012
¿PORQUÉ UN API?

                    Aumenta la flexibilidad de un servicio
                     Aumenta la utilidad de un servicio
                        Libera los datos de usuario




Friday, June 15, 2012
¿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
¿QUÉ
                   CARACTERÍSTICAS?




Friday, June 15, 2012
¿QUÉ
                   CARACTERÍSTICAS?
                        Fácil de implementar y mantener




Friday, June 15, 2012
¿QUÉ
                   CARACTERÍSTICAS?
                        Fácil de implementar y mantener
                        Buen rendimiento




Friday, June 15, 2012
¿QUÉ
                   CARACTERÍSTICAS?
                        Fácil de implementar y mantener
                        Buen rendimiento
                        Escalable




Friday, June 15, 2012
¿QUÉ
                   CARACTERÍSTICAS?
                        Fácil de implementar y mantener
                        Buen rendimiento
                        Escalable
                        Fácil de entender y usar



Friday, June 15, 2012
¿CUÁLES SON LOS
                            RETOS?




Friday, June 15, 2012
¿CUÁLES SON LOS
                            RETOS?

La red es un eslabón débil




Friday, June 15, 2012
¿CUÁLES SON LOS
                            RETOS?

La red es un eslabón débil
API incompleta pone estrés en el cliente




Friday, June 15, 2012
¿CUÁLES SON LOS
                            RETOS?

La red es un eslabón débil
API incompleta pone estrés en el cliente
Administrar Cambios




Friday, June 15, 2012
DISEÑAR UNA BUENA
                  API




Friday, June 15, 2012
CONVENCIONES REST




Friday, June 15, 2012
REST ⋍ CRUD

                                        GET /api/products #Listado
      {"products"	
  :	
  
      	
  	
  [
      	
  	
  	
  	
  {"product"	
  :	
  {	
  "id"	
  :	
  1,	
  "name"	
  :	
  "Producto	
  1",	
  "status"	
  :	
  "archived"}	
  },
      	
  	
  	
  	
  {"product"	
  :	
  {	
  "id"	
  :	
  2,	
  "name"	
  :	
  "Producto	
  2",	
  "status"	
  :	
  "active"	
  	
  }	
  }
      	
  	
  ]
      }




Friday, June 15, 2012
REST ⋍ CRUD

                                         GET /api/products/2 #Ver


      {"product"	
  :	
  {	
  "id"	
  :	
  2,	
  "name"	
  :	
  "Producto	
  2",	
  "status"	
  :	
  "active"	
  	
  }	
  }




Friday, June 15, 2012
REST ⋍ CRUD

                                      POST /api/products #Crear

      {
      	
  	
  "name"	
  :	
  "Producto	
  2"
      }




Friday, June 15, 2012
REST ⋍ CRUD
                              PUT /api/products/2 #Actualizar


      {
      	
  	
  "name"	
  :	
  "Producto	
  dos"
      }




Friday, June 15, 2012
REST ⋍ CRUD
                        DELETE /api/products/2 #Eliminar




Friday, June 15, 2012
VERSIONANDO TU API


    • API          Interna (entre aplicaciones)

    • API          Externa (aplicacion movil ? )

    • API          Usuarios (publico en general)




Friday, June 15, 2012
VERSIONANDO TU API

                        /int/api/products
                        /ext/api/products
                        /pub/api/products




Friday, June 15, 2012
VERSIONANDO TU API

                        /int/api/products?version=2
                        /ext/api/products?version=2
                        /pub/api/products?version=2




Friday, June 15, 2012
VERSIONANDO TU API

                        /v2/int/api/products
                        /v2/ext/api/products
                        /v2/pub/api/products




Friday, June 15, 2012
MUNDO IDEAL




Friday, June 15, 2012
MUNDO IDEAL


Uso de: Accept Header




Friday, June 15, 2012
MUNDO IDEAL


Uso de: Accept Header


Accept: application/vnd.mycompany.com;version=2,application/json




Friday, June 15, 2012
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
CODIGOS HTTP

                        HTTP/1.1 401 Unauthorized

                        {
                            “errors”: [
                              “api_key not found”
                            ]
                        }




Friday, June 15, 2012
CODIGOS HTTP
                    HTTP/1.1 401 Unauthorized

                    {
                      “errors”: [
                        “api_key no valida”,
                        “api_key no puede contener
                    espacios”
                      ]
                    }




Friday, June 15, 2012
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
CODIGOS HTTP
      HTTP/1.1 400 Bad Request

      {
        “errors”: [
          “Estructura JSON no valida”,
          “unexpected TSTRING, expected ‘}’ at
      line 2”
        ]
      }



Friday, June 15, 2012
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
CODIGOS HTTP

                        HTTP/1.1 503 Service Unavailable

                        {
                            “messages”: [
                              “En mantenimiento”
                            ]
                        }




Friday, June 15, 2012
OPCIONES AVANZADAS

    • Simuladores

    • Autenticación

    • Validadores

    • Limite            de uso

    • Rapidez

    • Balanceo

Friday, June 15, 2012
USANDO RUBY ON
              RAILS PARA
         IMLEMENTAR UNA API



Friday, June 15, 2012
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
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
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
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
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
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
APIS ON RAILS
                                      VISTAS
    #app/views/api/v3/products/index.rabl

    collection @products
    attributes :id, :name, :status
    node(:url) {|product| product_url(product) }
    node(:current_stock) {|product| product.variants.map(&:on_hand).sum }
    child :variants do
      attributes :upc, :color, :size, :on_hand
    end




    {"products"	
  :	
  
    	
  	
  [
    	
  	
  	
  	
  {"product"	
  :	
  {	
  "id"	
  :	
  1,	
  "name"	
  :	
  "Producto	
  1",	
  "status"	
  :	
  "archived",	
  “current_stock”	
  :	
  10,
    	
  	
  	
  	
  	
  	
  “variants”	
  :	
  [	
  {“upc”	
  :	
  “ASDFS”,	
  “color”	
  :	
  “negro”,	
  “size”	
  :	
  “M”,	
  “on_hand”	
  :	
  10}	
  ]
    	
  	
  	
  	
  	
  	
  }
    	
  	
  	
  	
  }
    	
  	
  ]
    }



Friday, June 15, 2012
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
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
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
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
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
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
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
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
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
RAILS A DIETA




Friday, June 15, 2012
RAILS A DIETA

                          Rails es modular




Friday, June 15, 2012
RAILS A DIETA

                       Rails es modular
         Para crear APIs, algunos Middlewares no son
                             necesarios




Friday, June 15, 2012
RAILS A DIETA

                       Rails es modular
         Para crear APIs, algunos Middlewares no son
                             necesarios
                             rails-api



Friday, June 15, 2012
<Module:0x007ff271221e40>,
 ActionDispatch::Routing::Helpers,
 #<Module:0x007ff2714ad268>,
 ActionController::Base,
 ActionDispatch::Routing::RouteSet::MountedHelpers,
 HasScope,
 ActionController::Compatibility,
 ActionController::ParamsWrapper,
 ActionController::Instrumentation,
 ActionController::Rescue,
 ActiveSupport::Rescuable,
 ActionController::HttpAuthentication::Token::ControllerMethods,
 ActionController::HttpAuthentication::Digest::ControllerMethods,
 ActionController::HttpAuthentication::Basic::ControllerMethods,
 ActionController::RecordIdentifier,
 ActionController::DataStreaming,
 ActionController::Streaming,
 ActionController::ForceSSL,
 ActionController::RequestForgeryProtection,
 AbstractController::Callbacks,
 ActiveSupport::Callbacks,
 ActionController::Flash,
 ActionController::Cookies,
 ActionController::MimeResponds,
 ActionController::ImplicitRender,
 ActionController::Caching,
 ActionController::Caching::Fragments,
 ActionController::Caching::ConfigMethods,
 ActionController::Caching::Pages,
 ActionController::Caching::Actions,
 ActionController::ConditionalGet,
 ActionController::Head,
 ActionController::Renderers::All,
 ActionController::Renderers,
 ActionController::Rendering,
 ActionController::Redirecting,
 ActionController::RackDelegation,
 ActiveSupport::Benchmarkable,
 AbstractController::Logger,
 ActionController::UrlFor,
 AbstractController::UrlFor,
 ActionDispatch::Routing::UrlFor,
 ActionDispatch::Routing::PolymorphicRoutes,
 ActionController::HideActions,
 ActionController::Helpers,
 AbstractController::Helpers,
 AbstractController::AssetPaths,
 AbstractController::Translation,
 AbstractController::Layouts,
 AbstractController::Rendering,
 AbstractController::ViewPaths,
 ActionController::Metal,
 AbstractController::Base,
 ActiveSupport::Configurable,
 Object,
 ActiveSupport::Dependencies::Loadable,
 Mongoid::Extensions::Object::Yoda,
 Mongoid::Extensions::Object::Substitutable,
 Mongoid::Extensions::Object::Reflections,
 Mongoid::Extensions::Object::DeepCopy,
 Mongoid::Extensions::Object::Checks,
 JSON::Ext::Generator::GeneratorMethods::Object,
 PP::ObjectMixin,
 Kernel,
 BasicObject



Friday, June 15, 2012
<Module:0x007ff271221e40>,
 ActionDispatch::Routing::Helpers,
 #<Module:0x007ff2714ad268>,
 ActionController::Base,
 ActionDispatch::Routing::RouteSet::MountedHelpers,
 HasScope,
 ActionController::Compatibility,
 ActionController::ParamsWrapper,
 ActionController::Instrumentation,
 ActionController::Rescue,
 ActiveSupport::Rescuable,
 ActionController::HttpAuthentication::Token::ControllerMethods,
 ActionController::HttpAuthentication::Digest::ControllerMethods,
 ActionController::HttpAuthentication::Basic::ControllerMethods,
 ActionController::RecordIdentifier,                                #<Module:0x007f9211d5cd70>,
 ActionController::DataStreaming,                                    ActionDispatch::Routing::Helpers,
 ActionController::Streaming,                                        #<Module:0x007f9211f7b5e8>,
 ActionController::ForceSSL,                                         ActionController::API,
 ActionController::RequestForgeryProtection,                         ActiveRecord::Railties::ControllerRuntime,
 AbstractController::Callbacks,                                      ActionDispatch::Routing::RouteSet::MountedHelpers,
 ActiveSupport::Callbacks,                                           ActionController::Instrumentation,
 ActionController::Flash,                                            ActionController::Rescue,
 ActionController::Cookies,                                          ActiveSupport::Rescuable,
 ActionController::MimeResponds,                                     ActionController::DataStreaming,
 ActionController::ImplicitRender,                                   ActionController::ForceSSL,
 ActionController::Caching,                                          AbstractController::Callbacks,
 ActionController::Caching::Fragments,                               ActiveSupport::Callbacks,
 ActionController::Caching::ConfigMethods,                           ActionController::ConditionalGet,
 ActionController::Caching::Pages,                                   ActionController::Head,
 ActionController::Caching::Actions,                                 ActionController::Renderers::All,
 ActionController::ConditionalGet,                                   ActionController::Renderers,
 ActionController::Head,                                             ActionController::Rendering,
 ActionController::Renderers::All,                                   AbstractController::Rendering,
 ActionController::Renderers,                                        AbstractController::ViewPaths,
 ActionController::Rendering,                                        ActionController::Redirecting,
 ActionController::Redirecting,                                      ActionController::RackDelegation,
 ActionController::RackDelegation,                                   ActiveSupport::Benchmarkable,
 ActiveSupport::Benchmarkable,                                       AbstractController::Logger,
 AbstractController::Logger,                                         ActionController::UrlFor,
 ActionController::UrlFor,                                           AbstractController::UrlFor,
 AbstractController::UrlFor,                                         ActionDispatch::Routing::UrlFor,
 ActionDispatch::Routing::UrlFor,                                    ActionDispatch::Routing::PolymorphicRoutes,
 ActionDispatch::Routing::PolymorphicRoutes,                         ActionController::HideActions,
 ActionController::HideActions,                                      ActionController::Metal,
 ActionController::Helpers,                                          AbstractController::Base,
 AbstractController::Helpers,                                        ActiveSupport::Configurable,
 AbstractController::AssetPaths,                                     Object,
 AbstractController::Translation,                                    JSON::Ext::Generator::GeneratorMethods::Object,
 AbstractController::Layouts,                                        ActiveSupport::Dependencies::Loadable,
 AbstractController::Rendering,                                      PP::ObjectMixin,
 AbstractController::ViewPaths,                                      Kernel,
 ActionController::Metal,                                            BasicObject
 AbstractController::Base,
 ActiveSupport::Configurable,
 Object,
 ActiveSupport::Dependencies::Loadable,
 Mongoid::Extensions::Object::Yoda,
 Mongoid::Extensions::Object::Substitutable,
 Mongoid::Extensions::Object::Reflections,
 Mongoid::Extensions::Object::DeepCopy,
 Mongoid::Extensions::Object::Checks,
 JSON::Ext::Generator::GeneratorMethods::Object,
 PP::ObjectMixin,
 Kernel,
 BasicObject



Friday, June 15, 2012
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
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
Gracias!

                        Preguntas?
                                      Edwin Cruz
                              edwin@crowdint.com
                                         @softr8

Friday, June 15, 2012

More Related Content

KEY
Api development with rails
PDF
Refactoring JavaScript Applications
PPTX
AHOY FB Hack Day 2017
PPTX
Rapid mobile development with Ionic framework - Voxxdays Ticino 2015
PDF
Ionic - Revolutionizing Hybrid Mobile Application Development
PDF
Rest basico
PDF
Rest Teoria E Pratica
PDF
REST - Representational state transfer
Api development with rails
Refactoring JavaScript Applications
AHOY FB Hack Day 2017
Rapid mobile development with Ionic framework - Voxxdays Ticino 2015
Ionic - Revolutionizing Hybrid Mobile Application Development
Rest basico
Rest Teoria E Pratica
REST - Representational state transfer

Similar to Diseño de APIs con Ruby (20)

PDF
Designing Usable APIs featuring Forrester Research, Inc.
PDF
Modern REST API design principles and rules.pdf
PDF
Ebook undisturbed rest-v1 [res_tful apis]
PDF
Be My API How to Implement an API Strategy Everyone will Love
PDF
Modern REST API design principles and rules.pdf
PDF
What is REST?
PPTX
Trends in Web APIs Layer 7 API Management Workshop London
PDF
Web APIs
PDF
API Workshop Amsterdam presented by API Architect Ronnie Mitra
PPTX
introduction about REST API
PDF
Apply API Governance to RESTful Service APIs using WSO2 Governance Registry a...
PDF
A Modern API Toolbox
PDF
PDF The Design of Web APIs Second Edition MEAP Arnaud Lauret download
PDF
What Makes a Great Open API?
PPSX
Advanced Web Development in PHP - Understanding REST API
PPTX
What is an API?
PDF
The Design of Web APIs Second Edition MEAP Arnaud Lauret
PPTX
Best Practices in Api Design
PDF
RESTful applications: The why and how by Maikel Mardjan
PPTX
Undisturbed rest chapter01
Designing Usable APIs featuring Forrester Research, Inc.
Modern REST API design principles and rules.pdf
Ebook undisturbed rest-v1 [res_tful apis]
Be My API How to Implement an API Strategy Everyone will Love
Modern REST API design principles and rules.pdf
What is REST?
Trends in Web APIs Layer 7 API Management Workshop London
Web APIs
API Workshop Amsterdam presented by API Architect Ronnie Mitra
introduction about REST API
Apply API Governance to RESTful Service APIs using WSO2 Governance Registry a...
A Modern API Toolbox
PDF The Design of Web APIs Second Edition MEAP Arnaud Lauret download
What Makes a Great Open API?
Advanced Web Development in PHP - Understanding REST API
What is an API?
The Design of Web APIs Second Edition MEAP Arnaud Lauret
Best Practices in Api Design
RESTful applications: The why and how by Maikel Mardjan
Undisturbed rest chapter01
Ad

More from Software Guru (20)

PDF
Hola Mundo del Internet de las Cosas
PDF
Estructuras de datos avanzadas: Casos de uso reales
PPTX
Building bias-aware environments
PDF
El secreto para ser un desarrollador Senior
PDF
Cómo encontrar el trabajo remoto ideal
PDF
Automatizando ideas con Apache Airflow
PPTX
How thick data can improve big data analysis for business:
PDF
Introducción al machine learning
PDF
Democratizando el uso de CoDi
PDF
Gestionando la felicidad de los equipos con Management 3.0
PDF
Taller: Creación de Componentes Web re-usables con StencilJS
PPTX
El camino del full stack developer (o como hacemos en SERTI para que no solo ...
PDF
¿Qué significa ser un programador en Bitso?
PDF
Colaboración efectiva entre desarrolladores del cliente y tu equipo.
PDF
Pruebas de integración con Docker en Azure DevOps
PDF
Elixir + Elm: Usando lenguajes funcionales en servicios productivos
PDF
Así publicamos las apps de Spotify sin stress
PPTX
Achieving Your Goals: 5 Tips to successfully achieve your goals
PDF
Acciones de comunidades tech en tiempos del Covid19
PDF
De lo operativo a lo estratégico: un modelo de management de diseño
Hola Mundo del Internet de las Cosas
Estructuras de datos avanzadas: Casos de uso reales
Building bias-aware environments
El secreto para ser un desarrollador Senior
Cómo encontrar el trabajo remoto ideal
Automatizando ideas con Apache Airflow
How thick data can improve big data analysis for business:
Introducción al machine learning
Democratizando el uso de CoDi
Gestionando la felicidad de los equipos con Management 3.0
Taller: Creación de Componentes Web re-usables con StencilJS
El camino del full stack developer (o como hacemos en SERTI para que no solo ...
¿Qué significa ser un programador en Bitso?
Colaboración efectiva entre desarrolladores del cliente y tu equipo.
Pruebas de integración con Docker en Azure DevOps
Elixir + Elm: Usando lenguajes funcionales en servicios productivos
Así publicamos las apps de Spotify sin stress
Achieving Your Goals: 5 Tips to successfully achieve your goals
Acciones de comunidades tech en tiempos del Covid19
De lo operativo a lo estratégico: un modelo de management de diseño
Ad

Recently uploaded (20)

PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Hindi spoken digit analysis for native and non-native speakers
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
gpt5_lecture_notes_comprehensive_20250812015547.pdf
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
Getting Started with Data Integration: FME Form 101
PPTX
1. Introduction to Computer Programming.pptx
PDF
A comparative study of natural language inference in Swahili using monolingua...
PPTX
Chapter 5: Probability Theory and Statistics
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PDF
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PDF
1 - Historical Antecedents, Social Consideration.pdf
PPTX
Tartificialntelligence_presentation.pptx
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
A Presentation on Touch Screen Technology
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PDF
DP Operators-handbook-extract for the Mautical Institute
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Hindi spoken digit analysis for native and non-native speakers
Univ-Connecticut-ChatGPT-Presentaion.pdf
cloud_computing_Infrastucture_as_cloud_p
gpt5_lecture_notes_comprehensive_20250812015547.pdf
Zenith AI: Advanced Artificial Intelligence
Getting Started with Data Integration: FME Form 101
1. Introduction to Computer Programming.pptx
A comparative study of natural language inference in Swahili using monolingua...
Chapter 5: Probability Theory and Statistics
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
DASA ADMISSION 2024_FirstRound_FirstRank_LastRank.pdf
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
1 - Historical Antecedents, Social Consideration.pdf
Tartificialntelligence_presentation.pptx
Unlocking AI with Model Context Protocol (MCP)
A Presentation on Touch Screen Technology
Building Integrated photovoltaic BIPV_UPV.pdf
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
DP Operators-handbook-extract for the Mautical Institute

Diseño de APIs con Ruby

  • 1. Diseño de APIs con Ruby Edwin Cruz @softr8 #SGRuby Friday, June 15, 2012
  • 2. PLAN • Que es una API • Como implementar una buena API • Usando Ruby on Rails para implementar una API • Patrones de diseño Friday, June 15, 2012
  • 3. Application Programming Interface “ Friday, June 15, 2012
  • 4. API Es una manera para comunicar dos aplicaciones entre ellas. Friday, June 15, 2012
  • 5. TIPOS DE API • Library • SDK • Web services Friday, June 15, 2012
  • 6. PRIMERAS API - SOAP Simple Object Access Protocol Friday, June 15, 2012
  • 7. REST REpresentation State Transfer Friday, June 15, 2012
  • 8. CRUD Create Altas Read Bajas Update Cambios Delete Consultas Friday, June 15, 2012
  • 9. REST ⋍ CRUD Friday, June 15, 2012
  • 10. REST ⋍ CRUD Recursos a través de URI Uso de verbos HTTP Friday, June 15, 2012
  • 11. REST-ISH + JSON Friday, June 15, 2012
  • 12. REST-ISH + JSON = Friday, June 15, 2012
  • 13. REST-ISH + JSON = Cosas Increibles Friday, June 15, 2012
  • 15. RECURSO Cualquier cosa expuesta mediante web Friday, June 15, 2012
  • 16. RECURSO Cualquier cosa expuesta mediante web Tienen una representación en datos Friday, June 15, 2012
  • 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
  • 19. REQUISITOS REST Separación de responsabilidades Friday, June 15, 2012
  • 20. REQUISITOS REST Separación de responsabilidades Cliente/Servidor Friday, June 15, 2012
  • 21. REQUISITOS REST Separación de responsabilidades Cliente/Servidor Sin estado Friday, June 15, 2012
  • 22. REQUISITOS REST Separación de responsabilidades Cliente/Servidor Sin estado “Cacheable” Friday, June 15, 2012
  • 23. REQUISITOS REST Separación de responsabilidades Cliente/Servidor Sin estado “Cacheable” Sistema a capas Friday, June 15, 2012
  • 24. REQUISITOS REST Separación de responsabilidades Cliente/Servidor Sin estado “Cacheable” Sistema a capas Interface uniforme Friday, June 15, 2012
  • 25. ¿PORQUÉ UN API? 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
  • 30. ¿QUÉ CARACTERÍSTICAS? Friday, June 15, 2012
  • 31. ¿QUÉ CARACTERÍSTICAS? Fácil de implementar y mantener Friday, June 15, 2012
  • 32. ¿QUÉ CARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Friday, June 15, 2012
  • 33. ¿QUÉ CARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Escalable Friday, June 15, 2012
  • 34. ¿QUÉ CARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Escalable Fácil de entender y usar Friday, June 15, 2012
  • 35. ¿CUÁLES SON LOS RETOS? Friday, June 15, 2012
  • 36. ¿CUÁLES SON LOS RETOS? La red es un eslabón débil Friday, June 15, 2012
  • 37. ¿CUÁLES SON LOS RETOS? La red es un eslabón débil API incompleta pone estrés en el cliente Friday, June 15, 2012
  • 38. ¿CUÁLES SON LOS RETOS? La red es un eslabón débil API incompleta pone estrés en el cliente Administrar Cambios Friday, June 15, 2012
  • 39. DISEÑAR UNA BUENA API Friday, June 15, 2012
  • 41. REST ⋍ CRUD GET /api/products #Listado {"products"  :      [        {"product"  :  {  "id"  :  1,  "name"  :  "Producto  1",  "status"  :  "archived"}  },        {"product"  :  {  "id"  :  2,  "name"  :  "Producto  2",  "status"  :  "active"    }  }    ] } Friday, June 15, 2012
  • 42. REST ⋍ CRUD GET /api/products/2 #Ver {"product"  :  {  "id"  :  2,  "name"  :  "Producto  2",  "status"  :  "active"    }  } Friday, June 15, 2012
  • 43. REST ⋍ CRUD POST /api/products #Crear {    "name"  :  "Producto  2" } Friday, June 15, 2012
  • 44. REST ⋍ CRUD PUT /api/products/2 #Actualizar {    "name"  :  "Producto  dos" } Friday, June 15, 2012
  • 45. REST ⋍ CRUD DELETE /api/products/2 #Eliminar 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
  • 51. MUNDO IDEAL Uso de: Accept Header 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
  • 68. APIS ON RAILS VISTAS #app/views/api/v3/products/index.rabl collection @products attributes :id, :name, :status node(:url) {|product| product_url(product) } node(:current_stock) {|product| product.variants.map(&:on_hand).sum } child :variants do attributes :upc, :color, :size, :on_hand end {"products"  :      [        {"product"  :  {  "id"  :  1,  "name"  :  "Producto  1",  "status"  :  "archived",  “current_stock”  :  10,            “variants”  :  [  {“upc”  :  “ASDFS”,  “color”  :  “negro”,  “size”  :  “M”,  “on_hand”  :  10}  ]            }        }    ] } 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
  • 78. RAILS A DIETA Friday, June 15, 2012
  • 79. RAILS A DIETA Rails es modular Friday, June 15, 2012
  • 80. RAILS A DIETA Rails es modular Para crear APIs, algunos Middlewares no son necesarios Friday, June 15, 2012
  • 81. RAILS A DIETA Rails es modular Para crear APIs, algunos Middlewares no son necesarios rails-api Friday, June 15, 2012
  • 82. <Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDispatch::Routing::RouteSet::MountedHelpers, HasScope, ActionController::Compatibility, ActionController::ParamsWrapper, ActionController::Instrumentation, ActionController::Rescue, ActiveSupport::Rescuable, ActionController::HttpAuthentication::Token::ControllerMethods, ActionController::HttpAuthentication::Digest::ControllerMethods, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionController::RecordIdentifier, ActionController::DataStreaming, ActionController::Streaming, ActionController::ForceSSL, ActionController::RequestForgeryProtection, AbstractController::Callbacks, ActiveSupport::Callbacks, ActionController::Flash, ActionController::Cookies, ActionController::MimeResponds, ActionController::ImplicitRender, ActionController::Caching, ActionController::Caching::Fragments, ActionController::Caching::ConfigMethods, ActionController::Caching::Pages, ActionController::Caching::Actions, ActionController::ConditionalGet, ActionController::Head, ActionController::Renderers::All, ActionController::Renderers, ActionController::Rendering, ActionController::Redirecting, ActionController::RackDelegation, ActiveSupport::Benchmarkable, AbstractController::Logger, ActionController::UrlFor, AbstractController::UrlFor, ActionDispatch::Routing::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, ActionController::HideActions, ActionController::Helpers, AbstractController::Helpers, AbstractController::AssetPaths, AbstractController::Translation, AbstractController::Layouts, AbstractController::Rendering, AbstractController::ViewPaths, ActionController::Metal, AbstractController::Base, ActiveSupport::Configurable, Object, ActiveSupport::Dependencies::Loadable, Mongoid::Extensions::Object::Yoda, Mongoid::Extensions::Object::Substitutable, Mongoid::Extensions::Object::Reflections, Mongoid::Extensions::Object::DeepCopy, Mongoid::Extensions::Object::Checks, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject Friday, June 15, 2012
  • 83. <Module:0x007ff271221e40>, ActionDispatch::Routing::Helpers, #<Module:0x007ff2714ad268>, ActionController::Base, ActionDispatch::Routing::RouteSet::MountedHelpers, HasScope, ActionController::Compatibility, ActionController::ParamsWrapper, ActionController::Instrumentation, ActionController::Rescue, ActiveSupport::Rescuable, ActionController::HttpAuthentication::Token::ControllerMethods, ActionController::HttpAuthentication::Digest::ControllerMethods, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionController::RecordIdentifier, #<Module:0x007f9211d5cd70>, ActionController::DataStreaming, ActionDispatch::Routing::Helpers, ActionController::Streaming, #<Module:0x007f9211f7b5e8>, ActionController::ForceSSL, ActionController::API, ActionController::RequestForgeryProtection, ActiveRecord::Railties::ControllerRuntime, AbstractController::Callbacks, ActionDispatch::Routing::RouteSet::MountedHelpers, ActiveSupport::Callbacks, ActionController::Instrumentation, ActionController::Flash, ActionController::Rescue, ActionController::Cookies, ActiveSupport::Rescuable, ActionController::MimeResponds, ActionController::DataStreaming, ActionController::ImplicitRender, ActionController::ForceSSL, ActionController::Caching, AbstractController::Callbacks, ActionController::Caching::Fragments, ActiveSupport::Callbacks, ActionController::Caching::ConfigMethods, ActionController::ConditionalGet, ActionController::Caching::Pages, ActionController::Head, ActionController::Caching::Actions, ActionController::Renderers::All, ActionController::ConditionalGet, ActionController::Renderers, ActionController::Head, ActionController::Rendering, ActionController::Renderers::All, AbstractController::Rendering, ActionController::Renderers, AbstractController::ViewPaths, ActionController::Rendering, ActionController::Redirecting, ActionController::Redirecting, ActionController::RackDelegation, ActionController::RackDelegation, ActiveSupport::Benchmarkable, ActiveSupport::Benchmarkable, AbstractController::Logger, AbstractController::Logger, ActionController::UrlFor, ActionController::UrlFor, AbstractController::UrlFor, AbstractController::UrlFor, ActionDispatch::Routing::UrlFor, ActionDispatch::Routing::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, ActionDispatch::Routing::PolymorphicRoutes, ActionController::HideActions, ActionController::HideActions, ActionController::Metal, ActionController::Helpers, AbstractController::Base, AbstractController::Helpers, ActiveSupport::Configurable, AbstractController::AssetPaths, Object, AbstractController::Translation, JSON::Ext::Generator::GeneratorMethods::Object, AbstractController::Layouts, ActiveSupport::Dependencies::Loadable, AbstractController::Rendering, PP::ObjectMixin, AbstractController::ViewPaths, Kernel, ActionController::Metal, BasicObject AbstractController::Base, ActiveSupport::Configurable, Object, ActiveSupport::Dependencies::Loadable, Mongoid::Extensions::Object::Yoda, Mongoid::Extensions::Object::Substitutable, Mongoid::Extensions::Object::Reflections, Mongoid::Extensions::Object::DeepCopy, Mongoid::Extensions::Object::Checks, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject 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
  • 86. Gracias! Preguntas? Edwin Cruz edwin@crowdint.com @softr8 Friday, June 15, 2012