バリデーション - lanchester/rails_environment GitHub Wiki

ページによってバリデーションを分ける

登録画面が複数ある場合、画面ごとにバリデーションを分けたい時があります。validatesメソッドはonオプションをとることでバリデートするタイミングを変更できます。

# model
validates :username, presence: true, on: :create
validates :username, presence: true, length:{maximum: 10}, on: :hoge # 名前も自由につけられる

# controller
@user = User.new(params)
@user.valid? # presenceのみバリデーションされる
@user.valid?(context: :hoge) # presenceとlengthがバリデーションされる

with_optionsでまとめて書くこともできます。

with_options on: :hoge do |hoge|
  hoge.validates :nickname, presence: true
  hoge.validates :avatar, presence: true
end
バリデーションするフィールドを指定する

上記は項目数が多い場合、それぞれのページ分同じ内容を書かなければならないためDRYではありません。フィールドを指定してバリデーションを行うメソッドを定義してみます。

# 指定したフィールドのみをvalid?する
def valid_fields?(*fields)
  return true if valid?
  flat_fields = fields.flatten.collect
  errors.messages.delete_if{|field, error| !flat_fields.include?(field) }
  errors.messages.empty?
end

delete_ifはブロック内が真のときキーと値を削除する破壊的メソッドです。戻り値はレシーバ自身です。 errors.messagesのハッシュのキー(フィールド)がfieldsで指定されていなければバリデーションに引っかからなかったとして除外します。

@user = User.new(username: "hoge", age: nil)
@user.valid?
#=> false
@user.valid_fields?(:username)
#=> true