Api development with rails

  • 1,836 views
Uploaded on

En esta platica trate de transmitir mejores practicas que se deben tener en cuenta cuando se diseña una API, y como ruby on rails te podria ayudar a desarrollarla en muy poco tiempo

En esta platica trate de transmitir mejores practicas que se deben tener en cuenta cuando se diseña una API, y como ruby on rails te podria ayudar a desarrollarla en muy poco tiempo

More in: Technology , Business
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,836
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
23
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide
  • \n
  • Mi plan es hablarles acerca de las famosas y muy comunmente usadas APIs, como implementar una buena API que todo mundo quedra usarla y como ruby on rails te ayudara a hacerla en muy poco tiempo\n
  • dicho de una manera mas sencilla:\n\n
  • Asi como las interfaces de usuario ayudan a los usuarios a comunicarse con las aplicaciones, las apis ayudan a comunicar dos softwares distintos entre ellos\n
  • Estas son algunos ejemplos de APIs, pueden ser tanto como librerias como SDK’s, el problema con esto, es que generalmente tienen que ser usadas en el mismo lenguaje de programacion, por ejemplo Net::HTTP es un ejemplo de la API de ruby para establecer conexiones http\n
  • Estas fueron las primeras API’s que se empezaron a consumir en el mundo web, luego llegaron las wsdl’s y generalmente eran con mensajes en xml demaciaaado complejas, en esta platica quiero enfocarme a algunas mejores practicas para implementar apis usando las nuevas caracteristicas que se agregaron al http 1.1, especificamente al famoso REST\n
  • REST nacio en la implementacion de HTTP 1.1, de alguna manera fue mejora del 1.0, y no es mas que un estilo o convension para transferir datos entre el servidor web y el navegador. REST es una manera de organizar recursos con url’s unicas por lo tanto, es un patron de diseño para web services\n\nQue requisitos debe tener una aplicacion para ser RESTful ?\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • El server se encarga del almacenamiento, el cliente se encarga de la UI y del estado.\n\nSin estado significa que ninguna llamada REST depende de llamadas pasadas, ocea que el servidor no mantiene ningun valor del cliente en sesion \n\nLa respuesta puede ser cacheable por el cliente o no, se debe de expresar explicitamente, para evitar que el cliente tenga copias obsoletas - Incrementa escalabilidad -\n\nEl cliente nunca podra saber si esta conectado al servidor final - balanceo de cargar, cache -\n\nInterface uniforme es que tiene que ser lo más explicito posible el mensaje\n\n
  • operaciones comunes en sistemas de informacion, generalmente todo gira alrededor de estas operaciones basicas\n
  • \n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Representacion en datos, basicamente es un documento que se va a transferir del servidor al cliente\n\nOrigen de alguna informacion en especifico\n
  • Hace un momento comentaba de que los primeros web services usaban estructuras de datos basadas en definiciones xml, llegaban a ser mensajes demaciado grandes, y era complicado para un humano leerlas, entonces que pasa, si usamos una estructura mas sensilla?\nPorque JSON ?, si se te complica hacer una estructura con json, algo estas haciendo mal, mensajes son muy cortos, human readable, gzip\n
  • Hace un momento comentaba de que los primeros web services usaban estructuras de datos basadas en definiciones xml, llegaban a ser mensajes demaciado grandes, y era complicado para un humano leerlas, entonces que pasa, si usamos una estructura mas sensilla?\nPorque JSON ?, si se te complica hacer una estructura con json, algo estas haciendo mal, mensajes son muy cortos, human readable, gzip\n
  • Ejemplo: middleware\n
  • Ejemplo: middleware\n
  • Ejemplo: middleware\n
  • Como va a estar abierto a más personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • Como va a estar abierto a más personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • Como va a estar abierto a más personas, ejemplo de clientes, cuotas, \nnada de prametros ocultos, cuando regrese errores que los haga bien descriptivo\nbuena documentacion, eventos,\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • administracion de cambios\nsi tienes duda de que publicar en tu api, no la publiques, alguien mas la va a implementar y tendras que soportarla\n
  • \n
  • Una buena API siempre debe seguir convenciones REST, basicamente es seguir la convencion de un buen patron de diseño para solucionar este problema.\n\n
  • GET, POST, DELETE, PUT, etc\n
  • \n
  • \n
  • \n
  • \n
  • no regresaria ningun contenido, solo un http status code\n
  • \n
  • \n
  • muy dificil de adminsitrar, porque un solo controlador se encargaria de despachar todas las versiones\n
  • \n
  • \n
  • La informacion contenida en el header la utiliza el cliente y el servidor para ponerse de acuerdo como van a transmitir la informacion, esto significa que el cliente le esta diciendo al servidor que el soporta la version 2 de la api, y que debe regresarsela en modo json\n
  • La informacion contenida en el header la utiliza el cliente y el servidor para ponerse de acuerdo como van a transmitir la informacion, esto significa que el cliente le esta diciendo al servidor que el soporta la version 2 de la api, y que debe regresarsela en modo json\n
  • 401, Se excede la cuota mensual\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Mashery\nLimite de uso, para limitar a los usuarios de no hacer mal uso de los recursos, CDN pero para APIS, Balanceo de cargas\nOauth\nSandbox para probar\nbloqueo de IP’s, Accesos basados en roles\n
  • se puede aprovechar al maximo lo que rails ofrece para crear apis muy poderosa, rails ya tiene REST implementado, sistema de cache, autenticacion, logging de eventos, MVC, observers, se puede extender su funcionalidad muy facil, por ejemplo montarle un fulltext search engine como solr, es muy facil escribir pruebas unitarias\n
  • Rails ya nos da todo para hacer aplicaciones REST\n
  • Rails soporta namespaces para los recurcos nativamente, pero puede llegar a ser un problema al resolver los nombres de los controladores, para esto alguien mas ya hizo algo al respecto\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Funciona transparente con el .to_json, active_model_serializer es bueno para aplicaciones web que usan javascript frameworks como ember o backbone\n
  • \n
  • \n
  • \n
  • Las pruebas son muy importantes al momento de desarrollar cualquier software, existen herramientas que hacen de esto literalmente un placer, muy facil de automatizar las pruebas\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • basico para una api\n
  • basico para una api\n
  • basico para una api\n
  • \n
  • \n
  • \n
  • \n
  • \n

Transcript

  • 1. Diseño de APIs con Ruby Edwin Cruz @softr8
  • 2. PLAN• Que es una API• Como implementar una buena API• Usando Ruby on Rails para implementar una API• Patrones de diseño
  • 3. “ Application Programming Interface “
  • 4. API Es una manera para comunicar dosaplicaciones entre ellas.
  • 5. TIPOS DE API• Library• SDK• Web services
  • 6. PRIMERAS API - SOAP Simple Object Access Protocol
  • 7. RESTREpresentationStateTransfer
  • 8. REQUISITOS REST
  • 9. REQUISITOS RESTSeparación de responsabilidades
  • 10. REQUISITOS RESTSeparación de responsabilidadesCliente/Servidor
  • 11. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estado
  • 12. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”
  • 13. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capas
  • 14. REQUISITOS RESTSeparación de responsabilidadesCliente/ServidorSin estadoPuede ser “Cacheable”Sistema a capasInterface uniforme
  • 15. CRUDCreate AltasRead BajasUpdate CambiosDelete Consultas
  • 16. REST + CRUD
  • 17. REST + CRUD Recursos a través de URLs únicasUsando correctamente los verbos HTTP
  • 18. RECURSO
  • 19. RECURSOCualquier accion expuesta a travez de un servidorweb
  • 20. RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datos
  • 21. RECURSOCualquier accion expuesta a travez de un servidorwebTienen una representación en datosCon un servicio web intercambiamosrepresentaciones de recursos
  • 22. REST-ISH + JSON
  • 23. REST-ISH + JSON =
  • 24. REST-ISH + JSON = Cosas Increibles
  • 25. ¿PORQUÉ UN API?
  • 26. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones
  • 27. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones Proporciona valor de negocio
  • 28. ¿PORQUÉ UN API?Aumenta la flexibilidad y utilidad de tus aplicaciones Proporciona valor de negocio Ayuda a comunicar aplicaciones entre ellas
  • 29. ¿QUÉCARACTERÍSTICAS?
  • 30. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener
  • 31. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento
  • 32. ¿QUÉCARACTERÍSTICAS? Fácil de implementar y mantener Buen rendimiento Escalable
  • 33. ¿CUÁLES SON LOS RETOS?
  • 34. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientes
  • 35. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar Cambios
  • 36. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebido
  • 37. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de trafico
  • 38. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de traficoPicos de uso
  • 39. ¿CUÁLES SON LOS RETOS?La red es un eslabón débil, GEO localizacion de losclientesAdministrar CambiosUso indebidoBalanceo de traficoPicos de usoErrores
  • 40. DISEÑAR UNA BUENA API
  • 41. CONVENCIONES REST
  • 42. USAR CORRECTAMENTE VERBOS HTTP
  • 43. REST + CRUD GET /api/products #Listado{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived"} }, {"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } } ]}
  • 44. REST + CRUD GET /api/products/2 #Ver{"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } }
  • 45. REST + CRUD POST /api/products #Crear{ "name" : "Producto 2"}
  • 46. REST + CRUD PUT /api/products/2 #Actualizar{ "name" : "Producto dos"}
  • 47. REST + CRUDDELETE /api/products/2 #Eliminar
  • 48. VERSIONES DE LA API• API Interna (entre aplicaciones)• API Externa (aplicacion movil ? )• API Usuarios (publico en general)
  • 49. VERSIONANDO TU API /int/api/products /ext/api/products /pub/api/products
  • 50. VERSIONANDO TU API /int/api/products?version=2 /ext/api/products?version=2 /pub/api/products?version=2
  • 51. VERSIONANDO TU API /v2/int/api/products /v2/ext/api/products /v2/pub/api/products
  • 52. VERSIONANDO TU APIhttp://int.myapp.com/productshttp://api.myapp.com/products
  • 53. MUNDO IDEAL
  • 54. MUNDO IDEALUso de: Accept Header
  • 55. MUNDO IDEALUso de: Accept HeaderAccept: application/vnd.mycompany.com;version=2,application/json
  • 56. CODIGOS HTTP200 OK201 Created202 Accepted400 Bad Request401 Unauthorized402 Payment Required404 Not Found409 Conflict422 Unprocessable Entity500 Internal Server Error503 Service Unavailable
  • 57. CODIGOS HTTPHTTP/1.1 200 okGET /v1/products{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived"} }, {"product" : { "id" : 2, "name" : "Producto 2", "status" : "active" } } ]}
  • 58. CODIGOS HTTP HTTP/1.1 201 Created POST /v1/products { “product”: [ “name” : “name” ] }
  • 59. CODIGOS HTTPHTTP/1.1 400 Bad Request{ “errors”: [ “Estructura JSON no valida”, “unexpected TSTRING, expected ‘}’ atline 2” ]}
  • 60. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key not found” ]}
  • 61. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key no valida”, “api_key no puede contenerespacios” ]}
  • 62. CODIGOS HTTPHTTP/1.1 401 Unauthorized{ “errors”: [ “api_key no encontrada, por favorvisita http://account.myapp.com/api paraobtenerla” ]}
  • 63. CODIGOS HTTPHTTP/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 4numeros”, “ejemplo” : “SOL1234” ] ]}
  • 64. CODIGOS HTTPHTTP/1.1 500 Internal Server Error{ “exception”: [ “Base de datos no disponible” ]}
  • 65. CODIGOS HTTPHTTP/1.1 503 Service Unavailable{ “messages”: [ “En mantenimiento” ]}
  • 66. OPCIONES AVANZADAS• Simuladores• Autenticación• Validadores• Limite de uso• Rapidez• Balanceo
  • 67. USANDO RUBY ON RAILS PARAIMLEMENTAR UNA API
  • 68. APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do resources :productsend$ rake routes products GET /products(.:format) products#index POST /products(.:format) products#create new_product GET /products/new(.:format) products#newedit_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
  • 69. APIS ON RAILS - REST#config/routes.rbMyApp::Application.routes.draw do scope ‘/api’ do resources :products endend products GET /api/products(.:format) products#index POST /api/products(.:format) products#create new_product GET /api/products/new(.:format) products#newedit_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
  • 70. APIS ON RAILS - VERSIONESgem versionist#config/routes.rbMyApp::Application.routes.draw do api_version(:module => V1, :path => v2) do resources :products endend 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#newedit_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
  • 71. APIS ON RAILS, CONTROLADORclass V1::ProductsController < ApplicationController def index products = Product.paginate(:page => (params[:page] || 1), :per_page => (params[:per_page] || 100)).all render :json => products.to_json end def show product = Product.find(params[:id]) render :json => product.to_json end def update product = Product.find(params[:id]) product.update_attributes(params[:product]) render :json => product.to_json end def destroy product = Product.find(params[:id]) head product.destroy ? :ok : :unprocessable_entity endend
  • 72. APIS ON RAILS, CONTROLADORclass ApplicationController < ActionController::Base rescue_from ActiveRecord::UnknownAttributeError, ArgumentError do |exception| respond_with_error(exception, 400) end rescue_from ActiveRecord::RecordNotFound do |exception| respond_with_error(exception, 404) end rescue_from ActiveRecord::RecordInvalid do |exception| respond_with_error(exception, 422, errors: exception.record.errors.messages) end rescue_from RuntimeError do |exception| respond_with_error(exception, 500) end private def respond_with_error(exception, code, errors = {}) render json: {error: exception.class.to_s, message: exception.to_s, errors: errors}, status: code endend
  • 73. APIS ON RAILS, CONTROLADORclass V2::ProductsController < ApplicationController respond_to [:json, :xml, :html] 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 endend
  • 74. APIS ON RAILS - MODELOclass V2::Product < Product JSON_ATTRIBUTES = { properties: [ :id, :upc, :sku, :list_cost, :color, :dimension, :size, :created_at, :updated_at, ], methods: [ :units_on_hand ] }end
  • 75. APIS ON RAILS, CONTROLADORgem ‘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 endend
  • 76. APIS ON RAILS VISTAS#app/views/api/v3/products/index.rablcollection @productsattributes :id, :name, :statusnode(:url) {|product| product_url(product) }node(:current_stock) {|product| product.variants.map(&:on_hand).sum }child :variants do attributes :upc, :color, :size, :on_handend{"products" : [ {"product" : { "id" : 1, "name" : "Producto 1", "status" : "archived", “current_stock” : 10, “variants” : [ {“upc” : “ASDFS”, “color” : “negro”, “size” : “M”, “on_hand” : 10} ] } } ]}
  • 77. APIS ON RAILS VISTASgem ‘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_atend
  • 78. APIS ON RAILS VISTASgem ‘active_model_serializer’class PostSerializer < ActiveModel::Serializer attributes :id, :body attribute :title, :key => :name has_many :comments def tags tags.order :name endend
  • 79. APIS ON RAILS SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database authenticable,token authenticable, omniauthable, confirmable,recoverable, registerable, trackable, timeoutable,validatable, lockable
  • 80. APIS ON RAILS SEGURIDADDeviseAutenticacion Flexible para aplicaciones RailsCompuesta de 12 modulos: database authenticable,token authenticable, omniauthable, confirmable,recoverable, registerable, trackable, timeoutable,validatable, lockable
  • 81. APIS ON RAILS SEGURIDADgem ‘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 endend
  • 82. ESCRIBIENDO PRUEBAS
  • 83. APIS ON RAILS PRUEBASdescribe 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 endend
  • 84. APIS ON RAILS PRUEBASdescribe 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_response = JSON.parse(response.body) json_response[error].should == "ActiveRecord::RecordNotFound" json_response[message].should == "Couldnt find Product with id=-1" end end endend
  • 85. APIS ON RAILS PRUEBASdescribe 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 endend
  • 86. APIS ON RAILS PRUEBASdescribe 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 endend
  • 87. ROR, DEMACIADO PARA LAS API?• Helpers• Vistas• Administracion de assets• Generadores de html• Template engines
  • 88. <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, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject
  • 89. <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, #<Module:0x007f9211d5cd70>, ActionController::HttpAuthentication::Basic::ControllerMethods, ActionDispatch::Routing::Helpers, ActionController::RecordIdentifier, #<Module:0x007f9211f7b5e8>, ActionController::DataStreaming, ActionController::API, ActionController::Streaming, ActiveRecord::Railties::ControllerRuntime, ActionController::ForceSSL, ActionDispatch::Routing::RouteSet::MountedHelpers, ActionController::RequestForgeryProtection, ActionController::Instrumentation, AbstractController::Callbacks, ActionController::Rescue, ActiveSupport::Callbacks, ActiveSupport::Rescuable, ActionController::Flash, ActionController::DataStreaming, ActionController::Cookies, ActionController::ForceSSL, ActionController::MimeResponds, AbstractController::Callbacks, ActionController::ImplicitRender, ActiveSupport::Callbacks, ActionController::Caching, ActionController::ConditionalGet, ActionController::Caching::Fragments, ActionController::Head, ActionController::Caching::ConfigMethods, ActionController::Renderers::All, ActionController::Caching::Pages, ActionController::Renderers, ActionController::Caching::Actions, ActionController::Rendering, ActionController::ConditionalGet, AbstractController::Rendering, ActionController::Head, AbstractController::ViewPaths, ActionController::Renderers::All, ActionController::Redirecting, ActionController::Renderers, ActionController::RackDelegation, ActionController::Rendering, ActiveSupport::Benchmarkable, ActionController::Redirecting, AbstractController::Logger, ActionController::RackDelegation, ActionController::UrlFor, ActiveSupport::Benchmarkable, AbstractController::UrlFor, AbstractController::Logger, ActionDispatch::Routing::UrlFor, ActionController::UrlFor, ActionDispatch::Routing::PolymorphicRoutes, AbstractController::UrlFor, ActionController::HideActions, ActionDispatch::Routing::UrlFor, ActionController::Metal, ActionDispatch::Routing::PolymorphicRoutes, AbstractController::Base, ActionController::HideActions, ActiveSupport::Configurable, ActionController::Helpers, Object, AbstractController::Helpers, JSON::Ext::Generator::GeneratorMethods::Object, AbstractController::AssetPaths, ActiveSupport::Dependencies::Loadable, AbstractController::Translation, PP::ObjectMixin, AbstractController::Layouts, Kernel, AbstractController::Rendering, BasicObject AbstractController::ViewPaths, ActionController::Metal, AbstractController::Base, ActiveSupport::Configurable, Object, ActiveSupport::Dependencies::Loadable, JSON::Ext::Generator::GeneratorMethods::Object, PP::ObjectMixin, Kernel, BasicObject
  • 90. RAILS A DIETA
  • 91. RAILS A DIETA Rails es modular
  • 92. RAILS A DIETA Rails es modularPara crear APIs, algunos Middlewares no son necesarios
  • 93. RAILS A DIETA Rails es modularPara crear APIs, algunos Middlewares no son necesarios rails-api
  • 94. use ActionDispatch::Staticuse Rack::Lockuse#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fd3b32928c0>use Rack::Runtimeuse Rack::MethodOverrideuse ActionDispatch::RequestIduse Rails::Rack::Loggeruse ActionDispatch::ShowExceptionsuse ActionDispatch::DebugExceptionsuse ActionDispatch::RemoteIpuse ActionDispatch::Reloaderuse ActionDispatch::Callbacksuse ActionDispatch::CookiesuseActionDispatch::Session::CookieStoreuse ActionDispatch::Flashuse ActionDispatch::ParamsParseruse ActionDispatch::Headuse Rack::ConditionalGetuse Rack::ETaguseActionDispatch::BestStandardsSupportuse
  • 95. use ActionDispatch::Staticuse Rack::Lockuse use ActionDispatch::Static#<ActiveSupport::Cache::Strategy::Loc use Rack::LockalCache::Middleware:0x007fd3b32928c0> useuse Rack::Runtime #<ActiveSupport::Cache::Strategy::LocalCacuse Rack::MethodOverride he::Middleware:0x007fe74448cf50>use ActionDispatch::RequestId use Rack::Runtimeuse Rails::Rack::Logger use ActionDispatch::RequestIduse ActionDispatch::ShowExceptions use Rails::Rack::Loggeruse ActionDispatch::DebugExceptions use ActionDispatch::ShowExceptionsuse ActionDispatch::RemoteIp use ActionDispatch::DebugExceptionsuse ActionDispatch::Reloader use ActionDispatch::RemoteIpuse ActionDispatch::Callbacks use ActionDispatch::Reloaderuse ActionDispatch::Cookies use ActionDispatch::Callbacksuse useActionDispatch::Session::CookieStore ActiveRecord::ConnectionAdapters::Connectiuse ActionDispatch::Flash onManagementuse ActionDispatch::ParamsParser use ActiveRecord::QueryCacheuse ActionDispatch::Head use ActionDispatch::ParamsParseruse Rack::ConditionalGet use ActionDispatch::Headuse Rack::ETag use Rack::ConditionalGetuse use Rack::ETagActionDispatch::BestStandardsSupportuse
  • 96. RAILS-API?• ActiveRecord (manejo de errores)• Validaciones (responder a varios formatos)• Controladores, sistema de rutas (versionamiento)• Muchas librerias(Gems)• Autenticación (oauth, token, basic auth)• Mismos web servers confiables (mismo hosting)
  • 97. RAILS-API?• REST• CRUD
  • 98. CONCLUSION
  • 99. CONCLUSIONRails es perfecto para API’s!
  • 100. Gracias!Preguntas? Edwin Cruz edwin@crowdint.com @softr8