0
0

【豆知識】rails console から errors メソッドや full_message メソッドの返り値を確認する手順について

Posted at

はじめに

アプリ制作課題に取り組むと同時に過去課題を参考にしているわーちゃんです。今回はユーザー登録でバリデーションエラーが発生した場合、そのエラーメッセージを画面に表示するようなファイル設定、コードの記載を行ったあと、ローカルで確認することもできますが、ターミナルで確認できるようになってこそ!!大切だとおもったので、改めて学習しなおしてみました。
前回に比べて、「じゃあこの場合はどうなるのか?」という考えもできるようになってきたのでアウトプットの為にもまとめてみます。

さっそく手順

  1. rails console を起動
    docker compose exec web rails c で Rails コンソールを開く

  2. モデルのインスタンスを作成
    バリデーションエラーを確認するためには、モデルのインスタンスを作成し、そのインスタンスが無効な状態である必要があります。たとえば、User モデルがあると仮定します。

    user = User.new
    

    ここでは、User モデルの新しいインスタンスを作成します

  3. エラーメッセージの確認

    • errors メソッド
      errors メソッドを使用して、モデルインスタンスのエラーを確認できます。エラーオブジェクトは ActiveModel::Errors インスタンスです。

       user.errors
      

      これで、バリデーションエラーの詳細が表示されます。通常、エラーは属性ごとにグループ化されています。

    • full_messages メソッド
      full_messages メソッドを使用して、エラーメッセージをユーザーフレンドリーな形式で取得できます。

      user.errors.full_messages
      

      これで、全てのエラーメッセージが配列として表示されます。メッセージは属性名とエラーメッセージが組み合わさった形になります。

  4. 具体的なコード例
    例えば、User モデルが email 属性に対して presence バリデーションを持っている場合、email 属性が空のときにエラーメッセージを確認する方法は次の通りです。

    # Userモデルのインスタンスを作成(属性を設定せず)
    user = User.new
    
    # バリデーションを実行
    user.valid?
    
    # エラーオブジェクトを確認
    user.errors
    # => #<ActiveModel::Errors:0x00007f9b7c39e5e0 ...>
    
    # エラーメッセージを全て確認
    user.errors.full_messages
    # => ["Email can't be blank"]
    

エラーメッセージはどこに記述されているか

エラーメッセージは、Rails アプリケーションのモデル内で設定されているバリデーションに基づいています。具体的には、エラーメッセージはモデルファイル内に記述されています。以下のファイルや場所で設定されている可能性があります。

  • 1: モデルファイル内のバリデーション
    モデルファイル (app/models/user.rb など) 内で、バリデーションとそのエラーメッセージが定義されています。以下は例になります。

    class User < ApplicationRecord
      # バリデーション設定
      validates :email, presence: true
      validates :name, presence: true
      validates :password, presence: true, length: { minimum: 6 }
      validates :password_confirmation, presence: true
    end
    
  • 2:エラーメッセージのカスタマイズ
    デフォルトのエラーメッセージは、バリデーションのオプションで指定できます。例えば、password に対する length バリデーションでカスタムメッセージを指定することができます。

    validates :password, length: { minimum: 6, message: "is too short (minimum is %{count} characters)" }
    
  • 3: 国際化 (I18n) ファイル
    エラーメッセージは、国際化 (I18n) ファイルでカスタマイズされることもあります。config/locales/ ディレクトリ内にある YAML ファイル(例えば、config/locales/en.yml)でエラーメッセージを設定できます。

en:
 errors:
   messages:
     blank: "can't be blank"
     too_short: "is too short (minimum is %{count} characters)"

この設定によって、エラーメッセージがカスタマイズされると、デフォルトのメッセージが上書きされます。


実際の例1(あらためて解説付き)

$ docker compose exec web rails c
Loading development environment (Rails 7.1.3.4)
irb(main):001> user = User.new
=> 
#<User:0x00007fc3732abb18
...
irb(main):002> user.valid?
  User Exists? (0.8ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" IS NULL LIMIT $1  [["LIMIT", 1]]
=> false
irb(main):003> user.errors.full_messages
=>
["Password is too short (minimum is 6 characters)",
 "Password confirmation can't be blank",
 "Name can't be blank",
 "Email can't be blank"]
irb(main):004* user.errors.each do |error|
irb(main):005*   puts error.full_message
irb(main):006> end
Password is too short (minimum is 6 characters)
Password confirmation can't be blank
Name can't be blank
Email can't be blank
=>
[#<ActiveModel::Error attribute=password, type=too_short, options={:if=>#<Proc:0x00007fc37525f950 /myapp/app/models/user.rb:10 (lambda)>, :count=>6}>,
 #<ActiveModel::Error attribute=password_confirmation, type=blank, options={:if=>#<Proc:0x00007fc37525a770 /myapp/app/models/user.rb:12 (lambda)>}>,
 #<ActiveModel::Error attribute=name, type=blank, options={}>,
 #<ActiveModel::Error attribute=email, type=blank, options={}>]
irb(main):007> user.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=password, type=too_short, options={:if=>#<Proc:0x00007fc37525f950 /myapp/app/models/user.rb:10 (lambda)>, :count=>6}>, #<ActiveModel::Error attribute=password_confirmation, type=blank, options={:if=>#<Proc:0x00007fc37525a770 /myapp/app/models/user.rb:12 (lambda)>}>, #<ActiveModel::Error attribute=name, type=blank, options={}>, #<ActiveModel::Error attribute=email, type=blank, options={}>]>

1. user = User.new

このコードは仮のユーザーオブジェクトUser モデルのインスタンス)を作成しています。

  • 何のファイルに基づいているか: この仮のユーザーオブジェクトは、app/models/user.rb に定義された User モデルに基づいて作成されています。User.newUser クラスの新しいインスタンスを作成し、まだ保存されていないユーザーオブジェクトを作ります。

2. user.valid?

このコードは、User モデルに定義されているバリデーションが適用されるかどうかを確認するためのものです。

  • 動作の流れ:
    • app/models/user.rb で定義されたバリデーション(例: 必須フィールドや文字数制限など)が、この仮のユーザーオブジェクトに適用されます。
    • バリデーションに失敗すると false を返し、成功すると true を返します。

3. user.errors.full_messages

このコードは、バリデーションに失敗した場合に発生するエラーメッセージを表示するためのものです。

  • 動作の流れ:
    • user.valid? を実行した後、user.errors.full_messages を使って、発生したすべてのエラーメッセージを配列形式で返します。
    • これにより、どのフィールドでエラーが発生し、どのような問題があるかがわかります。

user.errors.each do |error| ... enduser.errors の違い

  • user.errors.each do |error| ... end:
    • エラーメッセージを1つずつ取り出して、何らかの処理(例えば puts error.full_message でメッセージを表示)を行うためのループです。このコードを実行すると、各エラーメッセージが順番にコンソールに出力されます。
  • user.errors:
    • これは、エラーの詳細を含む ActiveModel::Errors オブジェクトを返します。これには、どのフィールドにどのようなエラーが発生しているかが含まれています。

    • 例として、user.errors の返り値は以下のようになります:

      #<ActiveModel::Errors [#<ActiveModel::Error attribute=password, type=too_short, options={:count=>6}>, #<ActiveModel::Error attribute=email, type=blank, options={}>]>
      
    • このオブジェクトには、エラーメッセージそのものだけでなく、どの属性にどのようなタイプのエラーが発生しているかという詳細も含まれています。

実際の例1のまとめ

  • user = User.new: app/models/user.rb に基づいて仮のユーザーオブジェクトを作成。
  • user.valid?: user.rb で定義されたバリデーションを確認。
  • user.errors.full_messages: バリデーションエラーの内容を確認。
  • user.errors.each do |error| ... end: エラーメッセージを順番に処理。
  • user.errors: エラーの詳細情報を含むオブジェクトを確認。

実際の例2(例1との比較)

irb(main):003> user = User.new(name: 'Hoge')
=> 
#<User:0x00007f0889854100
...
irb(main):004> user.save
  TRANSACTION (0.4ms)  BEGIN
  User Exists? (1.6ms)  SELECT 1 AS one FROM "users" WHERE "users"."email" IS NULL LIMIT $1  [["LIMIT", 1]]
  TRANSACTION (0.5ms)  ROLLBACK
=> false
irb(main):005> user.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=password, type=too_short, options={:if=>#<Proc:0x00007f0889a25a10 /myapp/app/models/user.rb:10 (lambda)>, :count=>6}>, #<ActiveModel::Error attribute=password_confirmation, type=blank, options={:if=>#<Proc:0x00007f0889a24458 /myapp/app/models/user.rb:12 (lambda)>}>, #<ActiveModel::Error attribute=email, type=blank, options={}>]>
irb(main):006> user.errors.full_messages
=>
["Password is too short (minimum is 6 characters)",
 "Password confirmation can't be blank",
 "Email can't be blank"]
irb(main):007* user.errors.each do |error|
irb(main):008*   puts error.full_message
irb(main):009> end
Password is too short (minimum is 6 characters)
Password confirmation can't be blank
Email can't be blank
=>
[#<ActiveModel::Error attribute=password, type=too_short, options={:if=>#<Proc:0x00007f0889a25a10 /myapp/app/models/user.rb:10 (lambda)>, :count=>6}>,
 #<ActiveModel::Error attribute=password_confirmation, type=blank, options={:if=>#<Proc:0x00007f0889a24458 /myapp/app/models/user.rb:12 (lambda)>}>,
 #<ActiveModel::Error attribute=email, type=blank, options={}>]

コードの違いと説明

1. user = User.new(name: 'Hoge')

  • 意味: これは User クラスの新しいインスタンスを作成し、その際に name という属性に 'Hoge' という値を与えています。このオブジェクトはまだデータベースには保存されていません。
  • 違い: 先ほどのコードは何も属性を指定せずにユーザーオブジェクトを作成しましたが、このコードでは name が設定されています。

2. user.save

  • 意味: このメソッドは、user オブジェクトをデータベースに保存しようとします。保存が成功すれば true を返し、失敗すれば false を返します。
  • 違い: 先ほどのコードでは save を使用せず、user.valid? でオブジェクトが有効かどうかをチェックしていました。save はデータベースに保存するため、バリデーションが重要になります。

3. user.errors

  • 意味: これは user オブジェクトに関連するバリデーションエラーを保持しているオブジェクトです。save が失敗したとき、どの属性でエラーが発生したかを表示します。

4. user.errors.full_messages

  • 意味: バリデーションに失敗した場合のエラーメッセージを配列形式で取得します。例えば、["Name can't be blank", "Email can't be blank"] のような形で表示されます。

5. user.errors.each do |error|

  • 意味: user.errors を使って、個々のエラーメッセージをループで処理します。このコードでは、各エラーメッセージを puts を使って出力しています。

コードの違い

先ほどのコードでは user.valid? を使ってバリデーションを手動でチェックし、その後エラーメッセージを確認しました。一方で、こちらのコードでは save を使ってデータベースへの保存を試み、それに失敗した場合にエラーメッセージを確認する流れになっています。

  • save の意味: save は、オブジェクトが有効であればデータベースに保存し、無効であれば保存せず、エラー情報を保持します。
  • 順番の違い: save を使うことで、データベースへの保存が試みられるため、valid? ではなく save の結果に応じてエラー情報が格納されます。

この違いにより、save が成功するか失敗するかによって、エラーメッセージが異なる場合があります。

さいごに

rails consoleから返り値を確認することが無事できました。saveを使用する時と使用しないときとでは返ってくるこたえもかわり、凄いなぁとあらためて実感。
今回の記事が何か参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0