Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails para APIs

Rails para APIs

Veja como o Rails pode ser uma alternativa viável e muito melhor para a criação de APIs.

Nando Vieira

May 18, 2013
Tweet

More Decks by Nando Vieira

Other Decks in Programming

Transcript

  1. No Sinatra, você volta ao problema de ter que fazer

    tudo o que o Rails já fazia por você.
  2. # app/controllers/application_controller.rb class ApplicationController < ActionController::Base # Prevent CSRF attacks

    by raising an exception. # For APIs, you may want to use :null_session instead. # protect_from_forgery with: :exception end
  3. # app/services/body_data.rb class BodyData def initialize(params) @params = params end

    def only(*attrs) @params.reduce({}) do |buffer, (key, value)| buffer[key] = value if attrs.include?(key.to_sym) buffer end end end
  4. { "repos": [ { "created_at": "2013-05-18T13:48:11.006Z", "name": "codeplane" }, {

    "created_at": "2013-05-18T13:48:17.109Z", "name": "howto" } ] }
  5. { "_links": { "self": { "href": "http://127.0.0.1:3000/repos" } }, "repos":

    [ { "_links": { "self": { "href": "http://127.0.0.1:3000/repos/1" } }, "created_at": "2013-05-18T13:48:11.006Z", "name": "codeplane" } ] }
  6. { "_links": { "locales": { "href": "http://localhost:3000/help/locales" }, "self": {

    "href": "http://localhost:3000/" }, "timezones": { "href": "http://localhost:3000/help/timezones" }, "users": { "href": "http://localhost:3000/users" } } }
  7. { "_links": { "self": { "href": "http://localhost:3000/help/locales" } }, "locales":

    [ { "code": "en", "name": "English" }, { "code": "pt-BR", "name": "Brazilian Portuguese" } ] }
  8. HTTP/1.1 200 OK Allow: POST Cache-Control: max-age=0, private, must-revalidate Connection:

    close Content-Encoding: gzip Content-Type: text/html ETag: "bfdba25abe4e2efd6ba82155b8aa0719" Server: thin 1.5.1 codename Straight Razor Vary: Accept-Language,Accept-Encoding,Origin X-Request-Id: ca7031fd-5190-4d9c-87b5-fac42dff926a X-Runtime: 0.036035
  9. # config/middleware/allowed_methods.rb class AllowedMethods attr_reader :verbs def initialize(*verbs) @verbs =

    verbs end def call(env) [ 200, { "Content-Type" => "text/html", "Allow" => verbs.map(&:upcase).join(",") }, [] ] end end
  10. { "errors": { "email": [ "is invalid" ], "name": [

    "can't be blank" ], "password": [ "can't be blank" ], "username": [ "is invalid" ] } }
  11. { "errors": { "email": [ "é inválido" ], "name": [

    "não pode ficar em branco" ], "password": [ "não pode ficar em branco" ], "username": [ "não é válido" ] } }
  12. class Locale attr_reader :app, :i18n def initialize(app, i18n = I18n)

    @app = app @i18n = i18n end def call(env) i18n.locale = env["HTTP_ACCEPT_LANGUAGE"] app.call(env) end end
  13. # app/controllers/application_controller.rb class ApplicationController < ActionController::Base before_action :require_authentication attr_reader :current_user

    def require_authentication authenticate_or_request_with_http_token do |token, options| @current_user = Authorizer.authorize(token) end end end
  14. require "openssl" # Request time timestamp = Time.now # Requested

    url url = "https://codeplane.com/repos" # API secret secret = "MYSUPERSECRET" # POST data options = {name: "myrepo"} # Hashing algorithm digest = OpenSSL::Digest::Digest.new("sha512")
  15. components = [url, secret, timestamp] components += options .keys .sort

    .reduce(components) do |buffer, key| buffer.concat [key, options[key]] end
  16. O Rack::Cache permite usar HTTP caching com headers de tempo

    de expiração (Expires, Cache- Control) ou validação (Etag, Last- Modified). https://github.com/rtomayko/rack-cache
  17. # config/initializers/middleware.rb Rails.configuration.middleware.tap do |middleware| # ... middleware.use ::Rack::Cache, :verbose

    => true, :metastore => "memcached://localhost:11211/meta", :entitystore => "memcached://localhost:11211/body" end
  18. HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Connection: close Content-Encoding:

    gzip Content-Type: application/json; charset=utf-8 ETag: "1358b2b2117fd019f60598f7a5514da2" Server: thin 1.5.1 codename Straight Razor Vary: Accept-Language,Accept-Encoding,Origin X-Request-Id: 4e7b55af-236c-4fcd-ae09-18d88e9019c0 X-Runtime: 0.071640
  19. HTTP/1.1 200 OK Cache-Control: max-age=0, private, must-revalidate Connection: close Content-Encoding:

    gzip Content-Type: application/json; charset=utf-8 ETag: "1358b2b2117fd019f60598f7a5514da2" Server: thin 1.5.1 codename Straight Razor Vary: Accept-Language,Accept-Encoding,Origin X-Request-Id: 4e7b55af-236c-4fcd-ae09-18d88e9019c0 X-Runtime: 0.071640