Rails控制器 – 仅当Rails UJS方法内部成功时才执行操作(相互依赖的方法)

接下来的另一个问题( Rails控制器 – 仅当内部两个方法成功时才执行操作(相互依赖的方法) ),我想确保在我的控制器的一个操作中,如果用户没有看到Rails UJS方法显示的消息,那么控制器动作的第一种方法也没有实现。

CONTEXT

我有一个控制器,其方法称为“动作”。 当应用程序进入方法’example_action’时,它实现第一个方法(1)update_user_table,然后(2)另一个update_userdeal_table。 (两者都将读写数据库),然后(3)第三种与Rails UJS(ajax)调用相关的方法。

我的问题如下:如果在控制器中间超时,我想避免更新User表(通过方法1),更新UserDeal表(通过方法2)但不更新thrid方法的情况即ajax请求显示消息FAILS(错误,超时,……状态如500或404或取消或超时……)。

在我的应用程序中,对于移动用户,如果他们在有地铁连接的地铁中,他们启动通过’example_action’控制器的请求,成功执行第一种方法(1)和第二种方法(2)但他们进入隧道非常低(<5b /秒)或无互联网连接60秒,因此出于用户体验原因,我超时请求并向用户显示'抱歉花了太长时间,再试一次'。 问题是,如果我无法向他们显示结果(3),我需要能够不执行(1)和(2)。

我需要两个方法(1)和(2)和(3)“相互依赖”:如果一个不成功,则不应该执行另一个。 这是我描述它的最佳方式。

今天这是我的代码。 它没有工作,因为我通过点击手动测试,然后在2秒后我断开了互联网连接。 我在我的数据库中看到(1)和(2)已执行并且数据库已更新,但我看到了“抱歉花了太长时间,再试一次”的消息。

这是正确的方法吗? 如果是的话怎么做? 如果没有,我应该尝试不同的角度:如果(1)和(2)成功但不是(3)我应该存储轨道UJS xhr状态是错误或超时的事实,因此模态wxas没有有效显示一旦他们重新上线,向用户显示结果/消息?

这是代码

用户html页面,用户点击触发Rails UJS aajax请求的按钮,该请求最终将显示模态消息

这将发送到指向此控制器操作的路由

交易控制器

 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 ); 

要管理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); }; }); 

因此,只有在抛出错误时,事务才会回滚。 如果抛出未处理的错误,您的应用程序将崩溃并以某种方式显示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 "); <% else %> showModalMessage("There was a problem"); <% end %> 

编辑:

处理连接问题绝对是棘手的,并没有真正理想的解决方案。 我通常会让数据库继续不间断地让它在自己的时间返回成功或失败。 对于冗长的事务,您可以使用像delayed_job或sidekiq这样的gem来处理后台的操作,并让rails控制器返回一个响应,说“……挂起……”或其他东西。 除非您在前端使用websockets,否则这意味着使用ajax请求不断轮询服务器以查看后台进程是否完整。