ActiveRecord::RecordNotUnique例外の発生をdisable_withで防ぐ

ActiveRecord::RecordNotUnique例外

(参考: Rails でDBの重複エラーが発生した場合の対処について – QA@IT)

RailsでModelの属性にvalidates_uniqueness_ofを設定しても, 内部ではその値が既存かどうかをselectでチェックしてからinsert/updateするだけなので, 同時に更新処理が行われた場合は重複してしまう可能性がある.

よって確実に一意性を保証するならDB側でcolumnをuniqueと宣言しておく必要がある.

このとき, DB側で重複エラーが発生した場合, ActiveRecord::RecordNotUnique例外が起こる.

対策としては, submitボタンをdisable_withして, ボタンの二度押しを防ぐ(JavaScriptで動く)こと. (わざわざ2画面から同時に登録しようとする人にはそのままエラーを返してもいいかもしれない)

disable_withの使い方

さてそのdisable_with, (form_for hoge do |f|となっているとする)

= f.submit "Submit", {disable_with: "Sending..."}

のようにして使う. (submit_tagでも同様)

すべてのsubmitにdisable_withを適用

(参考: tail -f pinzo.log: すべての submit に disable_with を)

個別のf.submitにいちいち{disable_with: 'Sending…'}とつけるのが面倒なら, config/initializers

module Helpers
  module FormTagHelper
    alias_method :original_submit_tag, :submit_tag
    def submit_tag(value=nil, options={})
      options[:disable_with] = t('sending') unless options[:disable_with]
      original_submit_tag value, options
    end
  end
end

と記述したファイルを足してやればよい.

もし, いくつかのsubmitだけdisable_withしたくない場合は,

として

f.submit 'Submit', {disabl_with: ''}

などとすれば, そのsubmitだけdisable_withをキャンセルできる.