Rails: リソースの一括登録画面: 3: 同一メールアドレスの登録防止
前回の続きです。同じメールアドレスを登録しようとすると画面にエラーメッセージを表示するようにします。それとDBの一意性バリデーションを追加します。
方針
メールアドレスの重複についてモデルとDBで一意性バリデーションをかける。
モデル
同じメールアドレスが存在すれば save!で ActiveRecord::RecordInvalid が発生する。
画面に該当のモデルのエラーメッセージを表示する。
DB
モデルのバリデーションが通った後に別端末などで同じメールアドレスが登録される場合がある。
トランザクションの完了時に ActiveRecord::RecordNotUnique が発生するので、画面に alert メッセージを表示する。
実装
DBの一意性バリデーションを追加します。
bin/rails g migration AddIndexToAccounts
class AddIndexToAccounts < ActiveRecord::Migration[7.0]
def change
add_index :accounts, :email, unique: true
end
end
bin/rails db:migrate
app/views/bulk_accounts/new.html.erb
notice と alert を表示できるようにします。
<p style="color: green"><%= notice %></p>
<p style="color: red"><%= alert %></p>
<h1>New accounts</h1>
...
app/controllers/bulk_accounts_controller.rb
save を save! に変更して例外を発生させます。
def create
is_success = false
@accounts = accounts_params.map { Account.new(_1).tap(&:valid?) }
ActiveRecord::Base.transaction do
is_success = @accounts.none? { _1.errors.any? } and @accounts.all?(&:save!)
raise ActiveRecord::RecordInvalid unless is_success
end
rescue ActiveRecord::RecordInvalid
is_success = false
rescue ActiveRecord::RecordNotUnique
is_success = false
flash.now[:alert] = "Account already exists."
ensure
if is_success
redirect_to new_bulk_account_url, notice: "Accounts were successfully created."
else
render :new, status: :unprocessable_entity
end
end
補足
一時的にモデルのバリデーションをコメントアウトして、トランザクションの完了時に ActiveRecord::RecordNotUnique を発生させ、画面に alert メッセージを表示させます。
class Account < ApplicationRecord
validates :name, :email, presence: true
# validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }, uniqueness: true
end
課題
見栄え(スタイリング)を良くしたい。
Account の登録数を増減できません。
以上です。
続きを書きました。
この記事が気に入ったらサポートをしてみませんか?