🦙

【Ruby on Rails】ログから確認する"status::unprocessable_entity"が必要な理由

2024/07/12に公開

はじめに

Ruby on Railsでフラッシュメッセージ、バリデーションのエラーメッセージを出力する際の挙動で、少し理解が浅い部分がありましたので備忘録として記載したいと思います。
具体的には、renderメソッド使用時になぜstatus::unprocessable_entityが必要なのかという内容になります。
今回、フラッシュメッセージ、バリデーションエラー出力に関する実装の説明は省略させていただきます。

参考になりましたら幸いです。

環境

Rails 7.1.3.4

ログ上で"status::unprocessable_entity"の有無を確認する

"status::unprocessable_entity"の記載がない場合

当初ユーザーの新規登録時、createアクション内の新規登録に失敗した際には、render :newのみ記載していました。
下記がその時のコード、実際のアプリ画面、サーバーログになります。

  • app/controllers/users_controller.rb
class UsersController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to articles_path, notice: '新規登録が完了しました。'
      # sorceryのオートログイン機能
      auto_login(@user)
    else
      flash[:alert] = '新規登録に失敗しました'
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end
end

GIF上でも、エラーメッセージ、バリデーションエラーが発生していないことがわかります。
Image from Gyazo

サーバーログを確認してみると、なぜエラーメッセージ、バリデーションエラーが発生していないかが理解できました。
サーバーログの一番下にCompleted 200 OKの記載が出ていることが確認できます。

MDNにも記載がある通り、

HTTP 200 OK はリクエストが成功した場合に返すレスポンスコード。

のため、クライアントへ正常なリクエストが渡っていると誤認させてしまっています。

Image from Gyazo

"status::unprocessable_entity"を記載した場合

何故エラーメッセージ、バリデーションエラーが出ないかを模索したところ、こちらの記事を拝見、renderメソッドの後ろに status: :unprocessable_entityを追記しました。
すると、画面上でもエラーメッセージとともにバリデーションエラーが出力されていることが確認できました。
(パスワードは最小8文字以上で設定しているため、5文字で入力しバリデーションエラーを出力させました)

  • app/controllers/users_controller.rb
class UsersController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to articles_path, notice: '新規登録が完了しました。'
      # sorceryのオートログイン機能
      auto_login(@user)
    else
      flash[:alert] = '新規登録に失敗しました'
      render :new, status: :unprocessable_entity
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end
end

GIF上でも、エラーメッセージ、バリデーションエラーが発生していることがわかります。
Image from Gyazo

サーバーログの一番下にCompleted 422 Unprocessable Contentの記載が出ていることが確認できます。

MDNにも記載がある通り、

The HyperText Transfer Protocol (HTTP) の 422 Unprocessable Entity 応答状態コードは、サーバーが要求本文のコンテンツ型を理解でき、要求本文の構文が正しいものの、中に含まれている指示が処理できなかったことを表します。

と記載があります。
status::unprocessable_entityを追記することで、クライアント側が、エラーが発生したことキャッチできるステータスコードへ変わったのです。

Image from Gyazo

まとめ

Railsガイドを確認してみても、こちらはRails7系から必須になっているようでした。(6系のRailsガイドには記載なし)
Railsガイドではstatus: :unprocessable_entityの具体的な記載が見受けられず、今回は個人記事を参照させていただきました。

スクールのカリキュラムで学習時は、なんとなくstatus: :unprocessable_entityをrenderメソッドの後ろに追記していました。
今回ログから確認してみることで、なぜstatus: :unprocessable_entityを追記する必要があるのか、その役割を確認することができました。
ありがとうございました。

参考

Discussion