vinibaggio.net

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:

{{< highlight javascript >}} my_callback({“foo”: “bar”}); {{< / highlight >}}

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

{{< highlight ruby >}} class EventsController < ApplicationController respond_to :json, :xml, :html

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

# ...

end {{< / highlight >}}

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:

  • Adicionei um handler JSONP para o meu Responder já existente (eu uso a gem responders);
  • Adicionei um Mime type para isso;
  • Adicionei respond_to :jsonp ao controller.

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 {{< highlight ruby >}} module JSONPResponder def tojsonp render :json => ”#{callback}(#{resource.tojson});” end

private def callback controller.params[:callback] end end {{< / highlight >}}

lib/application_responder.rb {{< highlight ruby >}} class ApplicationResponder < ActionController::Responder include Responders::FlashResponder include Responders::HttpCacheResponder include JSONPResponder end {{< / highlight >}}

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 {{< highlight ruby >}} Mime::Type.register_alias “application/javascript”, :jsonp {{< / highlight >}}

Adicionar respond_to :jsonp ao controller

Esse é o passo mais simples de todos:

{{< highlight ruby >}} class EventsController < ApplicationController respond_to :json, :jsonp, :xml, :html

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

# ...

end {{< / highlight >}}

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.


Vinicius Baggio Fuentes

Written by Vinicius Baggio Fuentes, who works in tech in NY but would rather be in the kitchen all the time. Twitter Instagram