【記事のテーマ】
初級者&中級者向けの書籍である『独習Ruby on Rails』を基準に
初学者である自分視点で「初級者&中級者向けの書籍には載っていないが公式のドキュメントには載っている少し上級よりな内容」
を取り上げることを目的としています。
(参考書籍)
(参考サイト)
バリデージョンの概要1
1.2 バリデーション実行時の動作
saveメソッドを実行したか否か
- Active Recordのオブジェクトには2種類存在
⇒既にDBにレコードとして入っているか否か- 言い換えれば
1)「モデルから生成しただけ」or「DBのレコードを取得してきたオブジェクト」
2)「これから新規レコードとして保存するオブジェクト」
の2種類がある
- 言い換えれば
- モデルオブジェクトを
new
メソッドでインスタンス生成しただけではDBに保存されてはいない - このインスタンスを
save
メソッドを呼ぶことでDBのテーブルに保存される- この「DBに
save
済みのインスタンスなのかどうか」を調べるメソッドにnew_record?
がある
- この「DBに
bin/rails consoleの出力で様子を観察してみます。
irb> p = Person.new(name: "John Doe") => #<Person id: nil, name: "John Doe", created_at: nil, updated_at: nil> irb> p.new_record? => true irb> p.save => true irb> p.new_record? => false
(Railsガイドより引用)
⇒このサンプルより、new_record?
で「save
をしていないインスタンス?」を真偽値として返しているため、save
メソッドの実行前後で返り値が異なる
DB保存に関連する破壊的メソッド
・create!
・save!
・update!
- 上記の
!
が末尾に付く破壊的メソッドは「オブジェクトが無効」な場合に例外が発生する- 普通のメソッド(非破壊メソッド)の場合は保存に失敗した場合には「false」を返す
(前略) irb> p.save => false irb> p.save! ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank irb> Person.create! ActiveRecord::RecordInvalid: Validation failed: Name can’t be blank
(Railsガイドより引用)
※一般的なのは「破壊的メソッドで呼び出した変数の値を変えてしまう」方だがそれとは別の意味を持っていることになる
バリデーションのスキップ
- バリデーションはDB保存実行時に必ず発生するが、オプションを渡せば意図的に回避できる
-
save(validate: false)
← 引数を渡している
-
以下、代表的なバリデーションをスキップするオブジェクト保存メソッド
-
insert_all
= 「直接SQLを実行して複数レコードを一括登録するためスキップ」 -
update_columns
= 「SQL文を発行してデータベースの属性を直接更新」
1.4 valid?とinvalid?
バリデーションの動作確認がしたい
- バリデーションがしっかり機能しているかどうかを確認したい時に
valid?
メソッドが有効- 手動でモデルに設けたバリデーション全てを実行確認できる
- "true":バリデーションを問題なく通過している
"false":バリデーションに引っかかっている = DBの値として不適切
- "true":バリデーションを問題なく通過している
- 手動でモデルに設けたバリデーション全てを実行確認できる
以下Railsガイドから引用したサンプルコードになる。
class Person < ApplicationRecord validates :name, presence: true end
irb> Person.create(name: "John Doe").valid? => true irb> Person.create(name: nil).valid? => false
(Railsガイドより引用)
バリデーションの失敗内容の確認がしたい
- バリデーションが行われて失敗するとエラー内容が
ActiveModel::Errors
クラスのインスタンス変数として管理される- DB保存に失敗したインスタンスから
errors()
メソッドを使ってアクセスする
- DB保存に失敗したインスタンスから
irb> p.valid? => false irb> p.errors.objects.first.full_message => "Name can't be blank"
(Railsガイドより引用)
-
errors[:attribute]
を使うと、特定のオブジェクトの属性が有効かどうかを確認できる-
errors[:name]
とすると「nameはレコード値として適切だったか否か」が分かる
-