2016-06-09 49 views
0

接下來的另一個問題(Rails controller - execute action only if the two methods inside succeed (mutually dependent methods)),我想確保在我的控制器的一個動作中,如果用戶沒有看到消息由Rails UJS方法顯示,那麼控制器操作的第一個方法也不會被執行。Rails控制器 - 只有Rails UJS方法成功時才執行動作(相互依賴的方法)

背景

我有一個名爲 '動作' 方法的控制器。當應用進入方法'example_action'時,它實現第一個方法(1)update_user_table,然後(2)另一個update_userdeal_table。 (都將讀取和寫入數據庫),然後(3)與Ra​​ils UJS(ajax)調用相關的第三種方法。

我的問題如下:在控制器中間超時的情況下,我想避免用戶表(通過方法1)更新,UserDeal表更新(通過方法2)的情況,但不是第三方法,即顯示消息FAILS(錯誤,超時,狀態如500或404或取消或超時...)的ajax請求。

在我的應用程序,對移動用戶,如果他們在與互聯網連接的地鐵,它們啓動,通過「example_action」控制器進入請求,成功地執行第一方法(1)和第二方法(2),但是然後他們以非常低的(< 5b/sec)或者沒有互聯網連接進入隧道60秒,所以出於UX的原因,我超時了請求並向用戶顯示,對不起花了太長時間,請重試。問題是,如果我不能向他們展示結果(3),我需要能夠不執行(1)和(2)。我需要兩個方法(1)和(2)和(3)「相互依賴」:如果一個不成功,另一個不應該被執行。這是我能描述它的最好方式。

今天這是我的代碼。它不起作用,因爲我通過點擊手動進行測試,然後在2秒鐘後斷開互聯網連接。我在我的數據庫中看到(1)和(2)已執行且數據庫已更新,但我看到消息'抱歉花了太長時間,請重試'。

這是正確的做法嗎?如果是的話,該怎麼做? 如果不是,我應該嘗試一個不同的角度,如:如果(1)和(2)是成功的,但不是(3)我是否應該存儲事實的軌道UJS xhr狀態是一個錯誤或超時,因此模式wxas沒有有效顯示給用戶,然後在他們恢復在線時向他們顯示結果/消息?

下面是代碼

html頁面爲用戶 上的按鈕的用戶點擊觸發一個Rails UJS aajax請求將顯示最終模式消息

<div id=zone"> 
    <%= link_to image_tag(smallest_src_request), 
      deal_modal_path, 
      remote: true %> 
</div> 

此發送到指向此控制器動作的路線

交易控制器

class DealsController < ApplicationController 
    def deal_modal 
    Deal.transaction do 
     update_user_table # that's the (1) 
     update_userdeal_table # that's the (2) 
     # show_modal_message 
     respond_to do |format| 
     format.js 
     end 
    end 

    private 
    def update_user_table 
    # update the table User so it needs to connect to internet and acces the distant User table 
    end 
    def update_userdeal_table 
    # update the table UserDeal table so it needs to connect to internet and access the distant UserDeal table 
    end 
end 

這指向一個js.erb視圖文件

deal_modal.js。ERB

showModalMessage("Here is your result <variable and all>); 

因爲AJAX,錯誤,超時...(如有必要,這個問題的解決),我使用的Rails UJS設置。

重要:正是在這裏,在錯誤或超時的情況下,我送自帶代替你通常得到的錯誤/超時模式消息(見上方「這是你的結果。」)

$(document).on('page:change', function() { 
     $("#zone"). 
     on('ajax:error',function(event,xhr, status, error){ 
      console.log(' ajax call failed:', error); 
      var msg; 
      msg = Messenger().post({ 
      hideAfter: 4, 
      message: "sorry it took too long, try again." 
      }); 
    }); 

$(document).on('page:change', function() { 
    //set timeout Rails UJS ajax option that will display message for ajax:error cases defined above 
    $.rails.ajax = function(options) { 
    if (!options.timeout) { 
     options.timeout = 5000; 
    }  
    return $.ajax(options); 
    }; 
}); 

回答

1

所以事務只會在拋出錯誤時回滾。如果拋出未處理的錯誤,您的應用程序將崩潰,並以某種方式顯示500錯誤。

爲了向用戶顯示響應,在成功或錯誤時,您將需要渲染一些東西。所以你不想阻止respond_to塊執行。處理這種情況的一種方法是通過實例變量設置標誌。

def deal_modal 
    begin 
    Deal.transaction do 
     update_user_table 
     update_userdeal_table 
    end 
    @success = true 
    rescue 
    @success = false 
    end 
    # show_modal_message 
    respond_to do |format| 
    format.js 
    end 
end 

然後在deal_modal.js.erb

<% if @success %> 
    showModalMessage("Here is your result <variable and all>"); 
<% else %> 
    showModalMessage("There was a problem"); 
<% end %> 

編輯:

與連接問題時肯定是棘手的,確實沒有一個理想的解決方案。我通常會讓數據庫不間斷地繼續運行,並讓它在自己的時間內成功或失敗。對於冗長的交易,您可以使用像delayed_jobsidekiq這樣的寶石來處理後臺中的操作,並讓rails控制器返回一個響應,說明「... pending ...」或其他內容。除非您在前端使用websockets,否則這意味着不斷使用ajax請求輪詢服務器以查看後臺進程是否完成。

+0

我會嘗試,但我不知道事務是否「習慣」/實際上可以捕獲「非紅寶石」錯誤。即如果軌道UJS拋出錯誤,如狀態'超時'或'錯誤'(這不是真正的紅寶石生態系統,但更多的JavaScript的事情),交易將它分類爲失敗,並移動到塊救援@成功=假? – Mathieu

+0

我認爲你的建議很酷,但不符合我的要求,或者我可能會誤解你的建議:我的目標是,如果導軌UJS(通過respond_to format.js)超時,則會回滾兩個第一個方法update_user_table和_updateuserdeal_table。從某種意義上說,它就像上一個問題:我想要這三種方法「聯合在一起」:如果第三種方法失敗,那麼我不希望2先執行(或者至少我希望它們回滾) – Mathieu

+0

我的當前代碼已經使我能夠向他們展示錯誤消息('抱歉太久了,再次嘗試'當它超時時:這已經起作用了。什麼都行不通,即使它向他們顯示Rails UJS錯誤消息('對不起太久了。 ..'),update_user和update_userdeal不會被回滾,數據庫的更新也不會被取消 – Mathieu

相關問題