LoginSignup
0
1

【+α】初学者がRailsガイドから知見を広げる('Active Record バリデーション'編 1)

Posted at

【記事のテーマ】
初級者&中級者向けの書籍である『独習Ruby on Rails』を基準に
初学者である自分視点で「初級者&中級者向けの書籍には載っていないが公式のドキュメントには載っている少し上級よりな内容」
を取り上げることを目的としています。


(参考書籍)

  1. 独習Ruby on Rails
  2. パーフェクトRuby on Rails 【増補改訂版】

(参考サイト)

  1. Railsガイド >> Active Record バリデーション
  2. Railsドキュメント
  3. Ruby on Rails API

バリデージョンの概要1

1.2 バリデーション実行時の動作

saveメソッドを実行したか否か

  • Active Recordのオブジェクトには2種類存在
    ⇒既にDBにレコードとして入っているか否か
    • 言い換えれば
       1)「モデルから生成しただけ」or「DBのレコードを取得してきたオブジェクト」
       2)「これから新規レコードとして保存するオブジェクト」
      の2種類がある
  • モデルオブジェクトをnewメソッドでインスタンス生成しただけではDBに保存されてはいない
  • このインスタンスをsaveメソッドを呼ぶことでDBのテーブルに保存される
    • この「DBにsave済みのインスタンスなのかどうか」を調べるメソッドにnew_record?がある

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 cant be blank

irb> Person.create!
ActiveRecord::RecordInvalid: Validation failed: Name cant be blank

(Railsガイドより引用)

※一般的なのは「破壊的メソッドで呼び出した変数の値を変えてしまう」方だがそれとは別の意味を持っていることになる

バリデーションのスキップ

  • バリデーションはDB保存実行時に必ず発生するが、オプションを渡せば意図的に回避できる
    • save(validate: false) ← 引数を渡している

以下、代表的なバリデーションをスキップするオブジェクト保存メソッド

  • insert_all = 「直接SQLを実行して複数レコードを一括登録するためスキップ」
  • update_columns = 「SQL文を発行してデータベースの属性を直接更新」

1.4 valid?とinvalid?

バリデーションの動作確認がしたい

  • バリデーションがしっかり機能しているかどうかを確認したい時にvalid?メソッドが有効
    • 手動でモデルに設けたバリデーション全てを実行確認できる
      • "true":バリデーションを問題なく通過している
        "false":バリデーションに引っかかっている = DBの値として不適切

以下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()メソッドを使ってアクセスする
irb> p.valid?
=> false
irb> p.errors.objects.first.full_message
=> "Name can't be blank"

(Railsガイドより引用)

  • errors[:attribute]を使うと、特定のオブジェクトの属性が有効かどうかを確認できる
    • errors[:name]とすると「nameはレコード値として適切だったか否か」が分かる
  1. https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E6%A6%82%E8%A6%81

0
1
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
1