2016-01-29 45 views
2

在我的Rails應用程序中的創建控制器中的respond_to塊沒有重定向保存成功...我相信這是一個簡單的解決方案,但我對Rails沒有經驗,這是第一個我遇到這個問題的時候。Rails的respond_to重定向不工作

的形式被設定爲使得:遠程=>爲真,並且該控制器被如下...

def create 
    @store = current_user.stores.new(store_params) 

    respond_to do |format| 
     if @store.save 
      format.html { redirect_to root_path } 
     else 
      format.html { flash[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
      render "new" } 
      format.js {} 
     end 
    end 
end 

雖然我在所述受試者中,從其他代碼的部條件不會運行,除了format.js {},它運行我的create.js.erb文件中的代碼(暫時是一個警報)。

我正在使用Rails 4.2.5。有人可以幫助我理解重定向和警報不起作用的原因嗎?謝謝!基於豐富的答案

編輯爲了顯示答案 ,這裏就是我想出瞭解決方案:

控制器:

def create 
    @store = current_user.stores.new(store_params) 

    flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" unless @store.save 

    respond_to do |format| 
     format.js 
    end 

    if @store.save 
     flash[:notice] = "New store created" 
    end 
end 

create.js.erb

<% if flash.now[:alert] %> 
    $("#alert_holder").empty(); 
    $("#alert_holder").append("<%= j flash.now[:alert] %>"); 
<% else %> 
    window.location.href = "<%= root_url %>"; 
<% end %> 

請注意,我需要在重定向網址中添加引號。

在表單成功時,頁面重定向到根目錄。失敗時,錯誤消息閃爍但表單未刷新 - 用戶輸入的任何答案仍然存在。

回答

3

remote: trueajax請求。

Ajax是JavaScript的,因此將調用format.js方法:

def create 
    @store = current_user.stores.new store_params 

    respond_to do |format| 
     if @store.save 
      format.js 
      format.html { redirect_to root_path } 
     else 
      format.js 
      format.html { flash[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
      render "new" } 
     end 
    end 
end 

format.js方法將調用/app/views/[:controller]/[:action].js.erb文件,這會觸發任何JS你在它裏面。

如果您不想使用js格式來處理回覆,那麼您必須取消respond_to並且只是想要返回(redirect_to將不起作用)。


阿賈克斯

有你需要這方面的體會到幾個規定:

  • 阿賈克斯不能 「重定向」(對自己)
  • 阿賈克斯將被視爲作爲您的Rails控制器中的JS
  • 您有「黑客」得到它通過JS

工作閃光燈。如果你沒有使用Ajax的經驗,簡單的解釋是,這是一個「僞請求」;它發送一個HTTP請求,而不必重新加載瀏覽器。

適合於Ajax的模式很簡單:Ajax request > server > Ajax response

你不能「重定向」通過Ajax,除非你解析與JavaScript的響應。由於Ajax的首字母縮寫(Asynchronous Javascript And XML)暗示,響應預期爲XML(IE沒有功能)。

-

要回答你的問題,你需要使用flash.now的「閃光」的消息,並處理與.js.erb文件的響應:

def create 
    @store = current_user.stores.new store_params 
    flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" unless @store.save 

    respond_to do |format| 
     format.js 
     format.html 
    end 
end 

這將允許你打電話......

#app/views/stores/create.js.erb 
<% if flash.now[:alert] %> alert("<%=j flash.now[:alert] %>"); <% end %> 
window.location.href = <%= root_url %>; 

Ref


您的新代碼就可以提高一點點:

def create 
    @store = current_user.stores.new store_params 

    if @store.save 
     flash[:notice] = "New store created" 
    else 
     flash.now[:alert] = "Save failed! #{@store.errors.full_messages.join(";")}" 
    end 

    respond_to do |format| 
     format.js 
    end 
end 

如果你想DRY你的代碼甚至更多,你要看看responders寶石:

#app/controllers/stores_controller.rb 
class StoresController < ApplicationController 
    respond_to :js, only: :create 

    def create 
     @store = ... 
     respond_with @store if @store.save 
    end 
end 
+0

哇!謝謝,這是一個美妙的解釋! – skwidbreth

+1

這真的很棒,我不會想到我自己。感謝您爲Rails新手提供指導。 – skwidbreth

+0

我編輯了我的問題,根據您的指導顯示我提出的答案。我不得不調整一些東西,但它完美的作品。 – skwidbreth

2

如果您的表格中有remote: true,則控制器檢測到的格式將爲format.js,而您的0123'部分中不存在格式。

2個選擇:

  • 默認爲正常的形式提交(刪除remote: true)加入format.js就像else子句中
  • 加載另一個js.erb文件然後執行錯誤通過一些JavaScript處理有。