Rails の ActiveRecord で、save! とかすると保存に失敗したとき例外を投げてくれる。例えば、User.create!(params[:user])
とかして、失敗すると、ActiveRecord::RecordInvalid
を投げてくれるのだけど、エラーをどうやって取るのか調べたのでメモ。
よくある例で、ユーザが作れたら index へ遷移して、作れなかったら new で再入力させるという場合。
createを使う場合
def create
if @user = User.create(params[:user])
flash[:notice] = 'ユーザ作成しました'
redirect_to action: :index
else
# ここでは、@user.errors でエラーが取れる
render action: :new
end
end
create!を使う場合
def create
@user = User.create!(params[:user])
flash[:notice] = 'ユーザ作成しました'
redirect_to action: :index
rescue ActiveRecord::RecordInvalid => e
# @user は nil になっているので、 @user.errors でエラーが取れない。
render action: :new
end
としたとき、create!
で例外が飛んでいるので、当然 @user
は nil
となってます。なので、rescue 句の中で @user.errors
ではエラーが取れません。
調べたところ、e.record
で、ActiveRecord の例外を発生させたインスタンスが取れるようです。
def create
@user = User.create!(params[:user])
flash[:notice] = 'ユーザ作成しました'
redirect_to action: :index
rescue ActiveRecord::RecordInvalid => e
# e.record に Userクラスのインスタンスが入ってる。
@user = e.record
render action: :new
end
たとえば、View内で
<%= error_messages_for :user %>
とかしたい場合は、 @user = e.record
としておけばエラーが楽に表示出来て良い。