Rails控制器-仅在内部的Rails UJS方法成功(相互依赖的方法)时才执行操作 [英] Rails controller - execute action only if the a Rails UJS method inside succeed (mutually dependent methods)

查看:92
本文介绍了Rails控制器-仅在内部的Rails UJS方法成功(相互依赖的方法)时才执行操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另一个问题( Rails controller-仅在内部的两个方法(相互依赖的方法)成功执行操作(相互依赖的方法),如果用户看不到Rails UJS方法显示的消息,我想确保在我控制器的一个操作内执行操作,那么控制器动作的第一个方法也不会实现.

Following another question (Rails controller - execute action only if the two methods inside succeed (mutually dependent methods)), I would like to ensure that inside one of my controller's action, if the user does not see the message displayed by a Rails UJS method, then the first methods of the controller action are not implemented either.

上下文

我有一个带有操作"方法的控制器.当应用进入方法'example_action'时,它实现第一个方法(1)update_user_table,然后(2)另一个update_userdeal_table. (都将读取和写入数据库),然后(3)与Ra​​ils UJS(ajax)调用相关的第三种方法.

I have a Controller with a method called 'actions'. When the app goes inside the method 'example_action', it implements a first method (1) update_user_table and then (2) another update_userdeal_table. (both will read and write database) and then (3) a third method which is related to a Rails UJS(ajax) call.

我的问题如下:在控制器中间超时的情况下,我想避免更新User表(通过方法1),UserDeal表(通过方法2)但未更新的情况第三种方法,即显示消息失败(错误,超时,...状态,如500或404或已取消或超时...)的ajax请求.

My issue is the following: in case of timeout in the middle of the controller, I want to avoid the case where the User table (via method 1) is updated, the UserDeal table is updated (via method 2) but NOT the thrid method i.e the ajax request that displays a message FAILS (error, timeout,...status like 500 or 404 or canceled or timeout...).

在我的应用中,对于移动用户,如果他们正在连接互联网的地铁中,他们将启动通过"example_action"控制器执行的请求,并成功执行第一种方法(1)和第二种方法(2)在非常低的速度(< 5b/sec)或没有Internet连接的情况下进入隧道60秒,因此出于UX原因,我使请求超时并向用户显示很抱歉,时间太长,请重试".问题是,如果我不能向他们显示结果(3),我就必须不能执行(1)和(2).

In my app, for mobile users if they're in a subway with internet connection, they launch the request that goes through 'example_action' controller, performs successfully the first method (1) and second method (2) but then they enter a tunnel for 60 seconds with very very low (<5b/sec) or NO internet connection, so for UX reasons, I timeout the request and display to the user 'sorry it took too long, try again'. The problem is that if I could not show to them the result (3), I need to be able to not execute (1) and(2).

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

I need the two methods (1) and(2) and(3) to be "mutually dependent": if one does not succeed, the other one should not be performed. It's the best way I can describe it.

今天这是我的代码.由于我正在通过单击进行手动测试,因此仅2秒钟后我断开了互联网连接,因此它无法正常工作.我在数据库中看到执行了(1)和(2)并更新了数据库,但是我看到了消息很抱歉,花了太长时间,请重试".

Today Here is my code. It's not working as I am manually testing by clicking and then after just 2 seconds I disconnect the internet connection. I see in my database that (1) and(2) were performed and the databases were updated but I saw the message 'sorry it took too long, try again'.

这是正确的方法吗?如果是,该怎么做? 如果不是,我是否应该尝试不同的角度,例如:如果(1)和(2)成功,但不是(3)我是否应该存储rails UJS xhr状态是错误或超时的事实,因此模式wx不能有效显示向用户显示,然后在他们重新上网后向他们显示结果/消息?

Is that the right approach ? if yes how to do this? If not, should I try a different angle like: if (1) and(2) were successful but not(3) should I store the fact the rails UJS xhr status was an error or timeout, that consequently the modal wxas not effectively displayed to the user and then show to them the result/message once they get back online?

这是代码

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

html page for the user the user click on a button that triggers a Rails UJS aajax request that will display ultimately the modal message

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

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

This send to a route that points to this controller action

交易控制器

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视图文件

This points to a js.erb view file

deal_modal.js.erb

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

要管理ajax,错误,超时...(如果有必要解决问题),我使用Rails UJS设置.

To manage the ajax, error, timeouts... (if necessary to the resolution of the question), I use Rails UJS settings.

重要提示::在这里,如果发生错误或超时,我将发送错误/超时模态消息,以代替您通常收到的消息(请参见上方的此处是您的结果" ..)

IMPORTANT: It is here that in case of error or timeout, I send the error / timeout modal message that comes in place of the one you normally get (see just above "Here is your result..")

$(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错误.

So the transaction will only rollback if an error is thrown. If an unhandled error is thrown, your application will crash and it will show a 500 error in some way.

为了向用户显示响应,无论是成功还是错误,您都需要渲染一些东西.因此,您不想阻止执行respond_to块.一种解决方法是通过实例变量设置标志.

In order to display the response to the user, on success or error, you will need to render something. So you don't want to prevent the respond_to block from executing. One way to handle this would be to set a flag via an instance variable.

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_job

Dealing with connection issues is definitely tricky and there isn't really one ideal solution. I would generally let the database continue uninterrupted and let it return either a success or failure on it's own time. For lengthy transactions, you can use a gem like delayed_job or sidekiq to process the action in the background and let the rails controller return a response saying "...pending..." or something. Unless you're using websockets on the frontend, this means continually polling the server with ajax requests to see if the background process is complete.

这篇关于Rails控制器-仅在内部的Rails UJS方法成功(相互依赖的方法)时才执行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆