【Rails】コールバックでターミナルにバリデーションエラーを出力する
◯◯.saveや◯◯.createに失敗する時の原因を教えてくれなくて困る
例えばmessageモデルのインスタンスのsaveに失敗した時
Started POST "/groups/2/messages" for ::1 at 2020-08-01 13:56:59 +0900
Processing by MessagesController#create as */*
Parameters: {"authenticity_token"=>"PKsrO+YPeqs8AmQ+sB+9YacFtKCb+gpdTkHPTgxG4/vs6wE0swZrWNYXKyBe4ipm9aQDII8PpHSUzL3JPeYPpw==", "message"=>{"content"=>""}, "group_id"=>"2"}
User Load (25.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 6 ORDER BY `users`.`id` ASC LIMIT 1
Group Load (0.6ms) SELECT `groups`.* FROM `groups` WHERE `groups`.`id` = 2 LIMIT 1
↳ app/controllers/messages_controller.rb:30:in `set_group'
(0.2ms) BEGIN
↳ app/controllers/messages_controller.rb:11:in `create'
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 6 LIMIT 1
↳ app/controllers/messages_controller.rb:11:in `create'
(0.2ms) ROLLBACK
ROLLBACK
とだけ出てパッと見では原因がわからない。
【対策1】コントローラでsave!を使う方法
save
やcreate
をsave!
、create!
にするとどのバリデーションが原因なのかエラーが表示される。
【対策2】モデルでコールバックを使う方法
本題。after_validation
を使ってself.errors.messages
などをputs
メソッドで表示する。
<メリット>
・deviseを使ったuserモデルのように、コントローラを触るのが面倒な場合でも使える
・application_record.rbに一度書けばそれぞれのモデルで使える
手順1. pry-railsのgemを導入する
バリデーションエラーが発生した場合にbinding.pryを走らせたいので、いつもどおりpry-railsのgemを導入する。
group :development, :test do
〜省略〜
gem 'pry-rails'
end
bundle
手順2. models/application_record.rbにコールバックを追加する
models/application_record.rb
に以下を追加する。
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
## 以下を追加する
after_validation :display_validation_result
private
def display_validation_result
## development以外のときはオフ
return false unless Rails.env.development?
puts "============【display_validation_result】============"
puts "◆◆◆◆◆◆#{self.class.name}モデル◆◆◆◆◆◆"
puts "+++++属性値一覧++++++"
self.attributes.each do |key, value|
puts "#{key}: #{value}"
end
## deviseを使ったuserモデルの場合passwordもputsする
if self.class.name == "User"
puts "password: #{self.password}"
end
puts "++++++++++++++++++++++++++++"
## メインはここから
puts "★★★★★★バリデーションエラー★★★★★★"
if self.errors.messages.length == 0
puts "発生しませんでした"
else
puts "バリデーションエラー発生"
puts self.errors.messages
binding.pry
end
puts "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★"
puts "==========================="
end
end
やっていることはバリデーションエラーが発生した時(self.errors.messages.lengthが0出ない時)にself.errors.messages
をターミナルに表示してbinding.pryを走らせているだけ。その他はおまけの情報。
結果
バリデーションエラーが発生してインスタンスのsaveに失敗する時、以下のようにターミナルに出力される。
============【display_validation_result】============
◆◆◆◆◆◆Userモデル◆◆◆◆◆◆
+++++属性一覧++++++
"id: "
"email: dwada"
"encrypted_password: $2a$11$zvwhx8qOe7u62tLbGQCaMOjItYjtjzg5yuaInysQ9wd15SMpMsBti"
"nickname: dadwa"
"first_name: dwadad"
"first_name_reading: dadawdwa"
"last_name: dwada"
"last_name_reading: dadwadwa"
"birthday: 2015-04-10"
"reset_password_token: "
"reset_password_sent_at: "
"remember_created_at: "
"password: dwadad"
++++++++++++++++++++++++++++
★★★★★★バリデーションエラー★★★★★★
バリデーションエラー発生
{:email=>["は不正な値です"], :password_confirmation=>["とパスワードの入力が一致しません"], :first_name_reading=>["はカタカナで入力して下さい。"], :last_name_reading=>["はカタカナで入力して下さい。"], :password=>["は不正な値です"]}
From: /Users/hogehoge/hogehoge/app/models/application_record.rb:27 ApplicationRecord#display_validation_result:
6: def display_validation_result
7: puts "============【display_validation_result】============"
8: puts "◆◆◆◆◆◆#{self.class.name}モデル◆◆◆◆◆◆"
9: puts "+++++属性一覧++++++"
10: self.attributes.each do |key, value|
11: p "#{key}: #{value}"
12: end
13:
14: if self.class.name == "User"
15: p "password: #{self.password}"
16: end
17:
18: puts "++++++++++++++++++++++++++++"
19: puts "★★★★★★バリデーションエラー★★★★★★"
20: if self.errors.messages.length == 0
21: puts "発生しませんでした"
22: else
23: puts "バリデーションエラー発生"
24: puts self.errors.messages
25: binding.pry
26: end
=> 27: puts "★★★★★★★★★★★★★★★★★★★★★★★★★★★★★"
28: puts "==========================="
29: end
[1] pry(#<User>)>
Author And Source
この問題について(【Rails】コールバックでターミナルにバリデーションエラーを出力する), 我々は、より多くの情報をここで見つけました https://qiita.com/rabi0102/items/2d102b92252fa2863faf著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .