Vinicius Baggio Fuentes

  1. Software Engineer — Pivotal Labs
  2. Autor — Casa do Código
  3. Compre já!
10 Mar 2011 — Jsonp Responder

Criando um Responder para JSONP no Rails 3

Recentemente eu tive que implementar uma feature no call4paperz que é responder dados dos eventos do site em JSONP.

JSONP é na verdade bem similar com a resposta JSON que o site já tinha, porém a resposta não mais é JSON puro, e sim um código JavaScript que chama um callback especificado. Quando a resposta do servidor for executada, esse callback é chamado automaticamente. Exemplo:

my_callback({"foo": "bar"});

Mas, para dar esse suporte, eu não queria arruinar os controllers que já estavam simples e elegantes, com o respond_with:

class EventsController < ApplicationController
    respond_to :json, :xml, :html

    def index
        @events = Event.all
        respond_with @events
    end

    # ...
end

Obviamente, senti a necessidade de criar um novo formato de resposta na aplicação. A API de Responders no Rails 3 funciona muito bem para isso. Dessa forma, eu:

Adicionar um handler JSONP

Como eu já tinha um Responder devido a gem, eu simplesmente adicionei o método to_jsonp a ele:

lib/jsonp_responder.rb

module JSONPResponder
  def to_jsonp
    render :json => "#{callback}(#{resource.to_json});"
  end

  private
  def callback
    controller.params[:callback]
  end
end

lib/application_responder.rb

class ApplicationResponder < ActionController::Responder
  include Responders::FlashResponder
  include Responders::HttpCacheResponder
  include JSONPResponder
end

Adicionar um Mime type

Como não há de fato um Mime type específico para JSONP, o site deverá responder como application/javascript, já que não respondemos mais JSON válido.

config/initializers/mime_types.rb

Mime::Type.register_alias "application/javascript", :jsonp

Adicionar respond_to :jsonp ao controller

Esse é o passo mais simples de todos:

class EventsController < ApplicationController
    respond_to :json, :jsonp, :xml, :html

    def index
        @events = Event.all
        respond_with @events
    end

    # ...
end

Finito!

Simples, não? O código do controller continua limpo como deveria ser, graças à API de Responders do Rails 3. Mais informações sobre ele pode ser visto em um blog post do próprio Rails.

Leia também

blog comments powered by Disqus