2016-06-09 18 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

相关问题