2011-03-25 153 views
4

我有这条线在我的票控制器:重定向不工作

before_filter :authenticate 

所以,当我投票,而注销,应该失败这个过滤器。

在我的应用程序控制器我的身份验证方法是这样的:

def authenticate 
    logged_in? ? true : access_denied 
end 

所以它返回access_denied看起来像这样:

def access_denied 
    redirect_to login_path, :notice => "You must log in to perform this action." and return false 
end 

所以,我应该被重定向到我的登录页面,向右?

我有这个在我的routes.rb文件:

match '/login' => "sessions#new", :as => "login" 

,我有一个new视图与登录表单,我应该被重定向到时候我投票,我没有登录我也。在我的票控制器的create方法验证码:

if @vote.save 
    respond_to do |format| 
     format.html { redirect_to @video } 
     format.js 
    end 
    else 
    respond_to do |format| 
     format.html 
    end 
    end 

但是,当我投票,我不重定向,并且我得到了我的日志此错误消息:

Started GET "/login" for 127.0.0.1 at Thu Mar 24 21:18:08 -0700 2011 
    Processing by SessionsController#new as JS 
Completed in 17ms 

ActionView::MissingTemplate (Missing template sessions/new with {:locale=>[:en, :en], :formats=>[:js, "*/*"], :handlers=>[:rhtml, :rxml, :erb, :builder, :rjs]} in view paths "/rubyprograms/dreamstill/app/views"): 

为什么会发生这种情况,以及如何才能使此重定向工作?

回答

6

看起来你似乎在向你的VotesController#create action发出一个javascript请求,但是你缺少一个用于Sessions#new的JS模板。

以下是会发生什么情况:您将VotesController#create调用为JS调用,并且当用户登录时全部都没问题,因为VotesController#会对JavaScript操作创建响应。问题是,如果用户没有登录,请求将重定向到SessionsController#new,并且请求仍然是一个javascript请求。问题是SessionsController#new没有响应JS,所以你得到一个缺少的模板错误。

我建议添加一个app/views/sessions/new.js.erb文件来处理JS调用。你现在可能只有一个app/views/sessions/new.html.erb文件。

您也可以通过使用javascript将HTML重定向到HTML请求来处理这种情况。您可以通过添加做到这一点下面你new.js.erb模板:

window.location = "<%= escape_javascript(login_path) %>"; 

这基本上都会告诉浏览器重定向到login_path好像请求是一项请求HTML,而不是一个Javascript请求。

+0

我已经更新了我的答案和更多的细节以及简单的重定向解决方案。 – 2011-03-25 01:39:40

+0

为什么我需要用于新会话的js文件?我不明白为什么我需要它,它应该包含什么内容......为什么当'@ vote.save'失败时,我不能仅仅使用正常的HTTP请求呢? – 2011-03-25 01:41:02

+0

如果请求是作为来自浏览器的Javascript请求发出的,例如通过AJAX请求发出,那么您无法用HTML内容响应,因为浏览器不知道如何处理响应。您需要使用Javascript进行响应,如我的示例代码,可以使用浏览器的JavaScript引擎运行。这就是HTTP协议的工作方式。这不是Rails特有的。 – 2011-03-25 01:45:31

1

由于导致问题的请求是ajax,请尝试在before_filter中添加一个检查以确定请求是否为js。

if request.xhr? 
    render :text => "document.location = '#{login_path}';", :layout => false 
else 
    redirect_to login_path, ... 
end 
+0

请问您能解释一下...我不明白它... – 2011-03-25 01:38:59

+0

正如上面所说的js请求不会以同样的方式对http响应做出响应。因此,如果301或302的重定向被返回,它会忽略它们,这就是为什么你要重定向发生,你必须添加js代码。我不喜欢把这样的代码放在new.js.erb文件中,因为js的处理是隐藏的。通过在控制器方法内回显js代码来保持清晰。 – chris 2011-03-25 01:53:35

+0

我发现这在我的ApplicationController中有用,我有一些全局的'rescue_from'条件。我发现我可以在'render'之前插入'flash [:alert] = message'语句,以在我重定向到的页面上获得“正常”错误消息。我指定'window.location',因为这显然是更普遍可写(http://stackoverflow.com/a/2430948/550712)。我不认为我可以分配302状态?当我将':status => 302'添加到'render'时,JavaScript没有执行。 – 2013-09-05 00:14:16