In rails controllers, how to prevent double submit (when user double-clic submit button or hit enter twice)?

后端 未结 8 2334
天命终不由人
天命终不由人 2021-02-19 09:50

Well, everything\'s in the title but I\'ll explain a little more :-)

My rails app contain many forms (Ajaxified or not).

To prevent users to submit twice or more

相关标签:
8条回答
  • 2021-02-19 09:55

    Here's what I'd do:

    1. Add a "token" field to an object in db that's about to be changed.
    2. Put that token into a form that modifies said object.
    3. Right after modification save that object with NEW token.
    4. Use that token in other page views.

    This will not prevent double submission, but at least will prevent the changes from second commit. I.e. when user submits the form second time the code will check the submitted token against the one in database and if they do not match - do not do an update to the object.

    This also has a draw back for newly created objects (i.e. if user want's to create a comment or smth like that). But in this case you may want to check the creation time interval from same user and if it's less than, say, 5 seconds - you'd prevent the object from being "created".

    0 讨论(0)
  • 2021-02-19 09:58

    Not a real suggestion (I won't be surprised of downvotes), but will your site still be usable without JS? How about showing him appropriate message that for normal operation he needs to enable the JS, otherwise you won't show him lots and lots of forms on the page.

    0 讨论(0)
  • 2021-02-19 10:03

    Try using Redis locking and surround your block with something like

    Redis.current.lock("#{current_user.id}.action_name") do
       # Some code
    end
    

    This is the gem I'm using https://github.com/mlanett/redis-lock

    0 讨论(0)
  • 2021-02-19 10:06

    You can add the option :disable_with => "Please Wait..." to the submit tag.

    0 讨论(0)
  • 2021-02-19 10:06

    I happen to face the same problem as well, and I have solved it with a very simple way(maybe it is not proper or it exists something buggy I didn't notice, please inform me if you found out)

    Here is my answer:

    $submitButton.on('click', function(e) {
      setTimeout(() => {
        $(this).attr('disabled', '');
      }, 0);
    });
    

    The main issue I was facing was that if I double clicked my original button, it would submit request twice and caused something unpredictable, so I tried to block the button with "disabled"attribute right after clicking it. Here is what I wrote.

    // !!this is an incorrect example!!
    $submitButton.on('click', function(e) {
        $(this).attr('disabled', '');
    });
    // !!don't copy this!!
    

    The biggest problem I was facing is that if I just disable the submit button right after clicking it, the submit request won't submit and the page will just hang there, as nothing ever happens.

    I think the cause is that the "disabled" attribute prevents the submit request from submitting.(Although I have no clue what the relationship between these two...)

    So, I think the disable event should be executed after submit event.

    As far as I understand, form submitting is a Javascript event, and setTimeout is an async method. As Javascript executes based on event loop, the ajax event will be put in the end of the event quene, and will be executed only after all the sync events finish.

    In my code, after the first click, the submit button will be disabled after 0 millisecond, which is impossible for human beings to click the second time, problem solved!

    0 讨论(0)
  • 2021-02-19 10:13

    Not sure if this is helpful:

    ON SERVERSIDE:

    1. On fresh load of the form, set a session['variable']=false //meaning the form isn't submitted yet.

    2. On form submit, check:

      if session['variable'] == true
      {
         do nothing...
      }
      else
      {
         set session['variable'] = true;
        //do submit logic here
      }
      
    0 讨论(0)
提交回复
热议问题