ActiveRecord の例外処理

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! で例外が飛んでいるので、当然 @usernil となってます。なので、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 としておけばエラーが楽に表示出来て良い。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です