在rails控制器中,如何防止双重提交(当用户双提交按钮或按两次输入时)?

fro*_*_oo 13 javascript forms controller ruby-on-rails double-submit-problem

好吧,一切都在标题中,但我会解释一下:-)

我的rails应用程序包含许多表单(Ajaxified或不Ajaxified).

为了防止用户提交两次或更多的表格,我使用Javascript.

有一个Ajaxified表单的场景:

  • 用户提交表格(clic或enter)
  • javascript禁用提交按钮
  • rails控制器执行操作(如Soap请求或DB中的插入)
  • rails控制器更新页面并在必要时启用提交按钮(如果有错误)

现在我想添加服务器端代码,以便在用户绕过javascript时保持真正干净.

有什么建议?

小智 8

您可以在提交标记中添加选项:disable_with =>"Please Wait ...".


小智 8

我在4个场景中使用4方法,请首先在这里更喜欢我的awnser:防止在Rails AJAX表单中提交双重提交

仅针对用户的点击限制:

使用stopImmediatePropagation并将click事件添加到目标dom.

  /**
   * ?????????
   * NOTICE: #1 ????????????? #2 stopImmediatePropagation ????????????????
   * @delay_duration ?????????
   */
  $.fn.preventMultipleClick = function (delay_duration) {
    delay_duration = delay_duration || 3000;
    var last_click_time_stamp = 0;
    var time_duration = 0;
    $(this).bind('click', function (event) {
      time_duration = last_click_time_stamp ? event.timeStamp - last_click_time_stamp : 0;
      //console.debug("preventMultipleClick", last_click_time_stamp, time_duration);
      if (time_duration && time_duration < delay_duration) {
        event.stopImmediatePropagation();
      } else {
        //console.debug("skip preventMultipleClick~");
        last_click_time_stamp = event.timeStamp;
      }
    });
  };
Run Code Online (Sandbox Code Playgroud)

限制提交,如ajax:

使用ajax的beforeSend attribut.

  /**
   * ???
   *   ?jquery?ajax???????:beforeSend
   *   ???beforeSend: function(){return $.preventMultipleAjax(event, 5000)}
   *
   * @param event
   * @param delay_duration
   * @returns {boolean}
   */
  $.preventMultipleAjax = function (event, delay_duration) {
    delay_duration = delay_duration || 3000;
    var target = $(event.target);
    var last_click_time_stamp = target.attr("_ajax_send_time_stamp") || 0;
    var time_duration = last_click_time_stamp ? event.timeStamp - last_click_time_stamp : 0;
    //console.debug("preventMultipleAjax", last_click_time_stamp, time_duration);
    if (time_duration && time_duration < delay_duration) {
      return false;
    } else {
      //console.debug("skip preventMultipleAjax~");
      target.attr("_ajax_send_time_stamp", event.timeStamp);
      return true;
    }
  };
Run Code Online (Sandbox Code Playgroud)

仅适用于表格:

<%= f.submit "Save annotation", :disable_with => "Saving...", :class => "btn btn-primary", :id => "annotation-submit-button" %>
Run Code Online (Sandbox Code Playgroud)

或:禁用:仅仅对表单元素,按钮等起作用,会阻止其上的事件触发

<input type="submit" value="submit" />
<input type="button" value="button" />
<input type="image" value="image" />
Run Code Online (Sandbox Code Playgroud)

其他:

这是宝石:https://github.com/mlanett/redis-lock

Redis.current.lock("#{current_user.id}.action_name") do
   # Some code
end
Run Code Online (Sandbox Code Playgroud)


Alo*_*urg 5

尝试使用Redis锁定并用类似的东西包围你的块

Redis.current.lock("#{current_user.id}.action_name") do
   # Some code
end
Run Code Online (Sandbox Code Playgroud)

这是我正在使用的宝石 https://github.com/mlanett/redis-lock