TLDR
Here’s an easy way to have all your SimpleForm submit buttons default to setting
data-disable-with
so that you don’t get errors when users double click on
submit buttons. If you’ve gotten a few ActiveRecord::RecordNotUnique
errors
that were hard to reproduce, then here’s your solution, with our without
SimpleForm. Additionally, using data-disable-with
provides the user with nice
feedback once a button is clicked.
ActiveRecord::RecordNotUnique Error!
If you’re using Devise, and you get a ActiveRecord::RecordNotUnique
error when
a new user is signing up, where do you look?
An ActiveRecord::RecordNotUnique occurred in registrations#create: PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_users_on_email" DETAIL: Key (email)=(somebody@yahoo.com) already exists. : INSERT INTO "users" ("address", "city", "confirmation_sent_at", "confirmation_token", "created_at", "default_location_id", "email", "encrypted_password", "first_name", "last_name", "mobile", "role", "state", "updated_at", "zip_code") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING "id"
At first, I was concerned that my unique index on my users table is not case insensitive. I started going down the road of converting my normal unique index on users.email to this index:
1
|
|
However, I soon figured out that Devise was already always saving email in the
database in lower case via a before_validation
hook.
So then I tried to double click the SAVE
button, and, BOOM, I got the same error.
data-disable-with=’Processing…’
A little bit of googling quickly revealed some handy rails techniques disabling
a submit button after being clicked, namely the setting of attribute
data-disable-with: “Some Message…” on both links and buttons. This works
nicely to fix the double submit RecordNotUnique error, and it provides some
sweet user feedback upon clicking a button. Here’s an example of a SAVE
button.
Immediately after clicking the SAVE
button, the button disables and the text changes.
Buttons
Example and API: button_tag
1
|
|
Links
Example and API: link_to
1
|
|
SimpleForm Submit Buttons
Even better, this can be done in one place for all SimpleForm submit buttons!
In a file like config/simple_form.rb
, place this initialization code:
1 2 3 4 5 6 7 8 |
|
What the bit of code above does is that it:
- Opens up the FormBuilder class to add a method
submit_with_override
. - Modifies options hash’s :data element, setting a default value for key
disable_with
that will not apply if there’s already a value there, thus allowing the default to be overridden by any individual button. - Calls alias_method_chain which makes is so that a call to submit actually
calls
submit_with_override
and that method can callsubmit_without_override
, which is the originalsubmit
method. The pattern of naming the methodswith_override
andwithout_override
is part of thealias_method_chain
call. Pretty darn cool!
Here’s a sample sign-up form that overrides the default “Processing…” label
when the SAVE
button is clicked.
1 2 3 4 5 6 7 |
|
Now go and click on some of your submit buttons, and they will all disable and
display “Processing…”. On a remote form that returned js.erb
, I had to send
back this line to reset the submit button:
1
|
|
References
Stack Overflow Discussions:
This is a companion discussion topic for the original entry at http://www.railsonmaui.com//blog/2014/02/23/simple-form-and-disable-processing-by-default/