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:
- Adicionei um handler JSONP para o meu Responder já existente (eu uso a gem responders);
- Adicionei um Mime type para isso;
- Adicionei
respond\_to :jsonpao 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
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.
Compre já!