blog

紫陽花

Rails Validationについて

データ管理はしっかりやりたい

DBにデータが保存される時に、そのデータが正しいかどうかを検証する仕組みをバリデーションという。

バリデーションのトリガー

バリデーションが走るメソッド群

  • create
  • create!
  • save
  • save!
  • update
  • update!

上記のメソッドはオプションでバリデーションをスキップすることも可能

save(validate: false)

バリデーションがスキップされるメソッド群

  • decrement!
  • decrement_counter
  • increment!
  • increment_counter
  • toggle!
  • touch
  • update_all
  • update_attribute
  • update_column
  • update_columns
  • update_counters

Validate

通常のバリデーションです。 modelに定義して利用します。

class Recipe < ActiveRecord::Base # これでtitleがnullだとデータのInsertが行われず、弾かれます validates :title, presence: true end

valid?invalid?が用意されておりboolean型の値が返ってきます。

Recipe.new(title: "レシピタイトル").valid?
#=> true

Recipe.new(title: null).valid?
#=> false

Recipe.new(title: "レシピタイトル").invalid?
#=> false

Recipe.new(title: null).invalid?
#=> true

カスタムValidate

単体のmodelで独自のvalidationを定義し、使いたい場合に利用する。

validate link_url_cannot_be_load

def link_url_cannot_be_load
  if @obj.url.include?(BASIC_DOMAIN)
    errors[:link_url] << "でURLは利用することができません。可能ドメインか確認してください"
  end
end 

カスタムValidator

複数のmodelで独自のvalidationを定義し、使いまわしたい場合に利用する。

もしくは単体のmodelでも複数の独自validationを定義し使いたい場合に利用する。

開発者にもよるが、自分は上記の理由と定義を決めている。ここは個人の好みにもよるのかもしれない・・・

そしてRailsのapp/以下にvalidators ディレクトリを作ってその中にカスタムvalidatorをまとめておく

カスタムバリデータはActiveModel::Validatorを拡張したクラス。

クラスにはvalidateメソッドが実装されている必要がある。

class Recipe << ActiveRecord::Base
  include ActiveModel::Validations
  validates_with ContentValidator
end

class ContentValidator < ActiveModel::Validator
  # 必ずvalidateメソッドを実装する
  # 引数にはレコードを1つ取り、それに対してのバリデーションを実行する
  def validate(record)
    if record.description.blank?
      record.errors[:description] << "が空です"
    end
  end
end
  • Validates
  • カスタムValidate
  • カスタムValidator

3つのバリデーションを使いこない堅牢なシステムを構築していきたい。

データまわりの定義は厳密に決めていくことが大切だと自分は考えています。

理由としては一度データが入ったデータベースは変更が難しくなってしまうからです。

アプリケーションレイヤーのvalidation制御はもちろん。

DB側での外部キー制約、ユニークキー制約、複数の一意制約、null制約などルールをしっかり決めておくことが大切。

新規開発においては、使用がコロコロ変わるのはしょっちゅうあるのである程度変更があることを前提に開発していくと良い。

ただ、リリース段階まで行く時にはきっちりと制約周りは定義することが守るべきルールとしてある。