Movatterモバイル変換


[0]ホーム

URL:


LoginSignup
59

Go to list of users who liked

39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsで特定のコンテキスト「以外」のときだけバリデーションする

Last updated atPosted at 2018-03-30

Railsのバリデーションは、:onオプションをつけることで任意のコンテキストのときだけ実行させることができます。

validates :name, presence: true # 常にバリデーションするvalidates :description, presence: true, on: :hoge # context: :hogeのときだけバリデーションする

しかし、context: :hoge以外のときだけバリデーションしたいときはどうすればいいのでしょうか。:on:hoge以外のコンテキストを全て指定するなどというのは流石にありえませんが、Railsガイドには説明がありません。

そのようにしたい場合は、以下のようにvalidation_contextを参照したlambdaやProcを:unlessに渡して条件を指定すれば実現できます。

validates :name, presence: true # 常にバリデーションするvalidates :description, presence: true, unless: -> { validation_context == :hoge } # context: :hoge以外のときだけバリデーションする

なぜこのような書き方になるのでしょうか。

まず:unlessで指定できるのは、以下のように:on:ifに読み替えており:on:ifは同等、:unlessは::ifの逆なので:unless:onの逆となるためです。

# https://github.com/rails/rails/blob/5-2-stable/activemodel/lib/active_model/validations.rb#L154def validate(*args, &block)  options = args.extract_options!  if args.all? { |arg| arg.is_a?(Symbol) }    options.each_key do |k|      unless VALID_OPTIONS_FOR_VALIDATE.include?(k)        raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?")      end    end  end  if options.key?(:on)    options = options.dup    options[:on] = Array(options[:on])    options[:if] = Array(options[:if])    options[:if].unshift ->(o) {      !(options[:on] & Array(o.validation_context)).empty?    }  end  set_callback(:validate, *args, options, &block)end

またvalidation_contextを参照できるのは、saveする際に呼ばれる以下の処理において、引数から渡ってきた:contextself.validation_contextにセットしているためです。

# https://github.com/rails/rails/blob/5-2-stable/activemodel/lib/active_model/validations.rb#L336def valid?(context = nil)  current_context, self.validation_context = validation_context, context  errors.clear  run_validations!ensure  self.validation_context = current_contextend

Railsでこの時だけ特定のバリデーションを検証したくないときしたこと
Rails のバリデーションを特定のコンテキスト「以外」で実行させる

なお条件付きバリデーションをwith_optionsでグループ化する記法がありますが、ここでも同様に、以下のようにvalidation_contextを参照して特定のコンテキスト以外の条件をグループ化することができます。

with_options unless -> { validation_context == :hoge } |not_hoge| # context: :hoge以外のときだけバリデーションする  not_hoge.validates :name, presence: true   not_hoge.validates :description, presence: trueend
59

Go to list of users who liked

39
2

Go to list of comments

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
59

Go to list of users who liked

39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?


[8]ページ先頭

©2009-2025 Movatter.jp