我正在尝试为我的Rails 3应用程序创建一个
JSONP API.现在在我的控制器中,我有很多遵循这种模式的动作:
- # This is from my users_controller.rb,as an example
- def index
- @users = User.all
- respond_with(@users,:callback => params[:callback])
- end
虽然这是按原样运作的,但我想通过不必重复:callback =>来干它.每个动作对respond_with的调用中的params [:callback].我怎样才能做到这一点?
更新:有一件事我已经意识到我上面的代码是丑陋的:callback => params [:callback]选项将被传递给任何响应格式,而不仅仅是JSON.以下代码可能更正确:
- def index
- @users = User.all
- respond_with(@users) do |format|
- format.json { render :json => @users,:callback => params[:callback]}
- end
- end
我有几种方法可以解决这个问题,但我无法弄清楚如何使它们工作:
>覆盖渲染(可能在应用程序控制器中),以便它接受:jsonp选项,该选项自动包含:callback => params [:callback]参数.这样我可以将上面的代码改为以下代码,这有点短:
- def index
- @users = User.all
- respond_with(@users) do |format|
- format.json { render :jsonp => @users}
- end
- end
>创建一个覆盖to_json的响应器以解决我的问题.这样我就可以省去块,只需调用respond_with(@users,:responder =>’MyResponder’)来解决问题.或许我可以使用plataformatec’s responders gem将此代码包含在应用程序响应程序中,以便respond_with(@users)本身就足够了.
解决方法
请注意,从技术上讲,使用回调参数呈现JSON是不正确的,因为您获得了JavaScript响应(对JSON-P回调的函数调用)而不是JSON结果.
所以,如果你有
所以,如果你有
- render :json => my_object,:callback => params[:callback]
并且对/ users?callback = func的请求进来了,Rails会回答
- func({…})
内容类型为application / json,这是不正确的,因为上面的响应显然不是JSON而是JavaScript.
我使用的解决方案是
- def respond_with_json(item)
- respond_with do |format|
- format.json { render :json => item }
- format.js { render :json => item,:callback => params[:callback] }
- end
- end
无论有没有回调,它都能正确响应.将此应用于上述解决方案,我们得到:
- def custom_respond_with(*resources,&block)
- options = resources.extract_options!
- if params[:callback]
- old_block = block
- block = lambda do |format|
- old_block.call(format) if block_given?
- format.js { render :json => resources[0],:callback => params[:callback] }
- end
- end
- respond_with(*(resources << options),&block)
- end
还要注意对资源[0]的更正,否则最终会因为splat运算符而将资源包装在额外的数组中.