关注另一个问题(Rails controller - execute action only if the two methods inside succeed (mutually dependent methods)),我想确保在我的一个控制器操作中,如果用户没有看到Rails UJS方法显示的消息,那么第一个方法控制器动作的任何一个都没有实现。
CONTEXT
我有一个名为' actions'的控制器。当应用程序进入方法' example_action'时,它实现第一个方法(1)update_user_table,然后(2)另一个update_userdeal_table。 (两者都将读写数据库),然后(3)第三种与Rails UJS(ajax)调用相关的方法。
我的问题如下:如果在控制器中间超时,我想避免更新User表(通过方法1),更新UserDeal表(通过方法2)但不是thrid方法,即显示消息FAILS的ajax请求(错误,超时,...状态如500或404或取消或超时......)。
在我的应用中,对于移动用户而言,如果他们是在有互联网连接的地铁中,他们就会启动通过&#39; example_action&#39;控制器,成功执行第一种方法(1)和第二种方法(2),但随后他们进入隧道60秒,非常低(<5b /秒)或没有互联网连接,因此出于UX原因,我超时请求并向用户显示'抱歉花了太长时间,再试一次&#39;。问题是,如果我无法向他们显示结果(3),我需要能够不执行(1)和(2)。
我需要两种方法(1)和(2)以及(3)相互依赖&#34;如果一个不成功,则不应该执行另一个。这是我描述它的最佳方式。
今天这是我的代码。它没有工作,因为我通过点击手动测试,然后在2秒后我断开了互联网连接。我在我的数据库中看到(1)和(2)已经执行并且数据库已更新,但我看到了消息“抱歉花了太长时间,再试一次”。
这是正确的方法吗?如果是的话怎么做? 如果没有,我应该尝试不同的角度:if(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设置。
重要提示:在这里,如果出现错误或超时,我会发送错误/超时模式消息代替您通常获得的消息(请参阅上面的#34;此处是你的结果..&#34;)
$(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);
};
});
答案 0 :(得分: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_job或sidekiq这样的gem在后台处理操作,并让rails控制器返回一个响应,说明&#34; ...等待......&# 34;或者其他的东西。除非您在前端使用websockets,否则这意味着不断使用ajax请求轮询服务器,以查看后台进程是否完整。