Rails 3:如何在Ajax调用中“redirect_to”?
提交login表单后,使用Ajax调用以下attempt_login
方法。
class AccessController < ApplicationController [...] def attempt_login authorized_user = User.authenticate(params[:username], params[:password]) if authorized_user session[:user_id] = authorized_user.id session[:username] = authorized_user.username flash[:notice] = "Hello #{authorized_user.name}." redirect_to(:controller => 'jobs', :action => 'index') else [...] end end end
问题是redirect_to
不起作用。
你将如何解决这个问题?
最后,我刚换了
redirect_to(:controller => 'jobs', :action => 'index')
有了这个:
render :js => "window.location = '/jobs/index'"
它工作正常!
有一个非常简单的方法来保持下一个请求的闪光灯。 在你的控制器中做类似的事情
flash[:notice] = 'Your work was awesome! A unicorn is born!' flash.keep(:notice) render js: "window.location = '#{root_path}'"
flash.keep
将确保闪存保留下一个请求。 所以当渲染root_path
时候,它会显示给定的flash消息。 Rails是真棒:)
我觉得这样稍微好一些:
render js: "window.location.pathname='#{jobs_path}'"
在我的一个应用程序中,我使用JSON来进行redirect和Flash消息数据。 它看起来像这样:
class AccessController < ApplicationController ... def attempt_login ... if authorized_user if request.xhr? render :json => { :location => url_for(:controller => 'jobs', :action => 'index'), :flash => {:notice => "Hello #{authorized_user.name}."} } else redirect_to(:controller => 'jobs', :action => 'index') end else # Render login screen with 422 error code render :login, :status => :unprocessable_entity end end end
简单的jQuery示例将是:
$.ajax({ ... type: 'json', success: functon(data) { data = $.parseJSON(data); if (data.location) { window.location.href = data.location; } if (data.flash && data.flash.notice) { // Maybe display flash message, etc. } }, error: function() { // If login fails, sending 422 error code sends you here. } })
结合所有最好的答案:
... if request.xhr? flash[:notice] = "Hello #{authorized_user.name}." flash.keep(:notice) # Keep flash notice around for the redirect. render :js => "window.location = #{jobs_path.to_json}" else ...
def redirect_to(options = {}, response_status = {}) super(options, response_status) if request.xhr? # empty to prevent render duplication exception self.status = nil self.response_body = nil path = location self.location = nil render :js => "window.location = #{path.to_json}" end end
我不想修改我的控制器操作,所以我想出了这个黑客:
class ApplicationController < ActionController::Base def redirect_to options = {}, response_status = {} super if request.xhr? self.status = 200 self.response_body = "<html><body><script>window.location.replace('#{location}')</script></body></html>" end end end