2011-03-25 129 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