SlideShare uma empresa Scribd logo
1 de 86
Baixar para ler offline
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

Mais conteúdo relacionado

Semelhante a Designing APIs with Ruby

PFCongres 2012 - Rock Solid Deployment of PHP Apps
PFCongres 2012 - Rock Solid Deployment of PHP AppsPFCongres 2012 - Rock Solid Deployment of PHP Apps
PFCongres 2012 - Rock Solid Deployment of PHP AppsPablo Godel
 
Welcome to Rails Girls Buenos Aires
Welcome to Rails Girls Buenos AiresWelcome to Rails Girls Buenos Aires
Welcome to Rails Girls Buenos AiresAnni Rautio
 
Migrations for Java
Migrations for JavaMigrations for Java
Migrations for JavaRafael Ponte
 
Quinn beginning wordpress_2012
Quinn beginning wordpress_2012Quinn beginning wordpress_2012
Quinn beginning wordpress_2012Sara Quinn
 
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)SNOW.or.kr
 
2012 SNOW 지식포럼 발표자료
2012 SNOW 지식포럼 발표자료 2012 SNOW 지식포럼 발표자료
2012 SNOW 지식포럼 발표자료 Ji Lee
 
Viestintäaamupäivä sharepoint 2013
Viestintäaamupäivä sharepoint 2013Viestintäaamupäivä sharepoint 2013
Viestintäaamupäivä sharepoint 2013Salcom Group
 
What’s new in LightSwitch 2013?
What’s new in LightSwitch 2013?What’s new in LightSwitch 2013?
What’s new in LightSwitch 2013?Robert MacLean
 
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...Corey Roth
 
ECommerce Data Management
ECommerce Data Management ECommerce Data Management
ECommerce Data Management Pure Visibility
 
Symfony2 y MongoDB - deSymfony 2012
Symfony2 y MongoDB - deSymfony 2012Symfony2 y MongoDB - deSymfony 2012
Symfony2 y MongoDB - deSymfony 2012Pablo Godel
 
Agile 2012 the 0-page agile test plan - paul carvalho
Agile 2012   the 0-page agile test plan - paul carvalhoAgile 2012   the 0-page agile test plan - paul carvalho
Agile 2012 the 0-page agile test plan - paul carvalhodrewz lin
 
CodeCamp Iasi 10 march 2012 - Infrastructure as code
CodeCamp Iasi 10 march 2012 - Infrastructure as codeCodeCamp Iasi 10 march 2012 - Infrastructure as code
CodeCamp Iasi 10 march 2012 - Infrastructure as codeCodecamp Romania
 
Easier with visual studio productivity tools
Easier with visual studio productivity toolsEasier with visual studio productivity tools
Easier with visual studio productivity toolsChris Eargle
 
API Days- Why is monitoring critical to API Management
API Days- Why is monitoring critical to API ManagementAPI Days- Why is monitoring critical to API Management
API Days- Why is monitoring critical to API ManagementWSO2
 
Development of IMPROV: A Provisioning Solution at UNC-Chapel Hill
Development of IMPROV: A Provisioning Solution at UNC-Chapel HillDevelopment of IMPROV: A Provisioning Solution at UNC-Chapel Hill
Development of IMPROV: A Provisioning Solution at UNC-Chapel Hillceleste_copeland
 
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...marcocasario
 
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access Control
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access ControlOAuth-as-a-service using ASP.NET Web API and Windows Azure Access Control
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access ControlMaarten Balliauw
 

Semelhante a Designing APIs with Ruby (20)

PFCongres 2012 - Rock Solid Deployment of PHP Apps
PFCongres 2012 - Rock Solid Deployment of PHP AppsPFCongres 2012 - Rock Solid Deployment of PHP Apps
PFCongres 2012 - Rock Solid Deployment of PHP Apps
 
Welcome to Rails Girls Buenos Aires
Welcome to Rails Girls Buenos AiresWelcome to Rails Girls Buenos Aires
Welcome to Rails Girls Buenos Aires
 
Migrations for Java
Migrations for JavaMigrations for Java
Migrations for Java
 
Quinn beginning wordpress_2012
Quinn beginning wordpress_2012Quinn beginning wordpress_2012
Quinn beginning wordpress_2012
 
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)
2012 SNOW 지식포럼 " 오픈 세상에서 배우다!" 오프닝 키노트-윤종수 판사(CCK)
 
2012 SNOW 지식포럼 발표자료
2012 SNOW 지식포럼 발표자료 2012 SNOW 지식포럼 발표자료
2012 SNOW 지식포럼 발표자료
 
SharePoint 2013 REST and CSOM
SharePoint 2013 REST  and CSOMSharePoint 2013 REST  and CSOM
SharePoint 2013 REST and CSOM
 
Viestintäaamupäivä sharepoint 2013
Viestintäaamupäivä sharepoint 2013Viestintäaamupäivä sharepoint 2013
Viestintäaamupäivä sharepoint 2013
 
What’s new in LightSwitch 2013?
What’s new in LightSwitch 2013?What’s new in LightSwitch 2013?
What’s new in LightSwitch 2013?
 
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...
What you need to know about Search in SharePoint 2013 Preview - DFW SharePoin...
 
ECommerce Data Management
ECommerce Data Management ECommerce Data Management
ECommerce Data Management
 
Symfony2 y MongoDB - deSymfony 2012
Symfony2 y MongoDB - deSymfony 2012Symfony2 y MongoDB - deSymfony 2012
Symfony2 y MongoDB - deSymfony 2012
 
Jenkins Evolutions
Jenkins EvolutionsJenkins Evolutions
Jenkins Evolutions
 
Agile 2012 the 0-page agile test plan - paul carvalho
Agile 2012   the 0-page agile test plan - paul carvalhoAgile 2012   the 0-page agile test plan - paul carvalho
Agile 2012 the 0-page agile test plan - paul carvalho
 
CodeCamp Iasi 10 march 2012 - Infrastructure as code
CodeCamp Iasi 10 march 2012 - Infrastructure as codeCodeCamp Iasi 10 march 2012 - Infrastructure as code
CodeCamp Iasi 10 march 2012 - Infrastructure as code
 
Easier with visual studio productivity tools
Easier with visual studio productivity toolsEasier with visual studio productivity tools
Easier with visual studio productivity tools
 
API Days- Why is monitoring critical to API Management
API Days- Why is monitoring critical to API ManagementAPI Days- Why is monitoring critical to API Management
API Days- Why is monitoring critical to API Management
 
Development of IMPROV: A Provisioning Solution at UNC-Chapel Hill
Development of IMPROV: A Provisioning Solution at UNC-Chapel HillDevelopment of IMPROV: A Provisioning Solution at UNC-Chapel Hill
Development of IMPROV: A Provisioning Solution at UNC-Chapel Hill
 
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...
HTML5 Italy: Back end ecosystems for your applications - Cesare Rocchi + Clau...
 
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access Control
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access ControlOAuth-as-a-service using ASP.NET Web API and Windows Azure Access Control
OAuth-as-a-service using ASP.NET Web API and Windows Azure Access Control
 

Mais de Software Guru

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

Mais de Software Guru (20)

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

Último

WomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneWomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneUiPathCommunity
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...amber724300
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityIES VE
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
 
Français Patch Tuesday - Avril
Français Patch Tuesday - AvrilFrançais Patch Tuesday - Avril
Français Patch Tuesday - AvrilIvanti
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...Karmanjay Verma
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 

Último (20)

WomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyoneWomenInAutomation2024: AI and Automation for eveyone
WomenInAutomation2024: AI and Automation for eveyone
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
JET Technology Labs White Paper for Virtualized Security and Encryption Techn...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
Decarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a realityDecarbonising Buildings: Making a net-zero built environment a reality
Decarbonising Buildings: Making a net-zero built environment a reality
 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
 
Français Patch Tuesday - Avril
Français Patch Tuesday - AvrilFrançais Patch Tuesday - Avril
Français Patch Tuesday - Avril
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...React JS; all concepts. Contains React Features, JSX, functional & Class comp...
React JS; all concepts. Contains React Features, JSX, functional & Class comp...
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 

Designing APIs with 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