Permalink
Browse files

Ability to specify multiple contexts when defining a validation.

Example:

validates_presence_of :name, on: [:update, :custom_validation_context]
  • Loading branch information...
1 parent 5540dfc commit 8855163bdbce23fa539be2c1ef2a49f1aabc6458 @vpuzzella vpuzzella committed Jan 18, 2014
View
20 activemodel/CHANGELOG.md
@@ -1,3 +1,23 @@
+* Ability to specify multiple contexts when defining a validation.
+
+ Example:
+
+ class Person
+ include ActiveModel::Validations
+
+ attr_reader :name
+ validates_presence_of :name, on: [:verify, :approve]
+ end
+
+ person = Person.new
+ person.valid? # => true
+ person.valid?(:verify) # => false
+ person.errors.full_messages_for(:name) # => ["Name can't be blank"]
+ person.valid?(:approve) # => false
+ person.errors.full_messages_for(:name) # => ["Name can't be blank"]
+
+ *Vince Puzzella*
+
* `attribute_changed?` now accepts parameters which check the old and new value of the attribute
`model.name_changed?(from: "Pete", to: "Ringo")`
View
14 activemodel/lib/active_model/validations.rb
@@ -66,8 +66,10 @@ module ClassMethods
# end
#
# Options:
- # * <tt>:on</tt> - Specifies the context where this validation is active
- # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt>)
+ # * <tt>:on</tt> - Specifies the contexts where this validation is active.
+ # You can pass a symbol or an array of symbols.
+ # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt> or
+ # <tt>on: [:create, :custom_validation_context]</tt>)
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
# * <tt>:allow_blank</tt> - Skip validation if attribute is blank.
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
@@ -124,8 +126,10 @@ def validates_each(*attr_names, &block)
# end
#
# Options:
- # * <tt>:on</tt> - Specifies the context where this validation is active
- # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt>)
+ # * <tt>:on</tt> - Specifies the contexts where this validation is active.
+ # You can pass a symbol or an array of symbols.
+ # (e.g. <tt>on: :create</tt> or <tt>on: :custom_validation_context</tt> or
+ # <tt>on: [:create, :custom_validation_context]</tt>)
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine
# if the validation should occur (e.g. <tt>if: :allow_validation</tt>,
# or <tt>if: Proc.new { |user| user.signup_step > 2 }</tt>). The method,
@@ -141,7 +145,7 @@ def validate(*args, &block)
options = options.dup
options[:if] = Array(options[:if])
options[:if].unshift lambda { |o|
- o.validation_context == options[:on]
+ Array(options[:on]).include?(o.validation_context)
}
end
args << options
View
16 activemodel/test/cases/validations/validations_context_test.rb
@@ -36,4 +36,20 @@ def validate(record)
assert topic.invalid?(:create), "Validation does run on create if 'on' is set to create"
assert topic.errors[:base].include?(ERROR_MESSAGE)
end
+
+ test "with a class that adds errors on multiple contexts and validating a new model with no arguments" do
+ Topic.validates_with(ValidatorThatAddsErrors, on: [:context1, :context2])
+ topic = Topic.new
+ assert topic.valid?, "Validation doesn't run when 'on' is set to context1 and context2"
+ end
+
+ test "with a class that adds errors on multiple contexts and validating a new model" do
+ Topic.validates_with(ValidatorThatAddsErrors, on: [:context1, :context2])
+ topic = Topic.new
+ assert topic.invalid?(:context1), "Validation does run on context1 when 'on' is set to context1 and context2"
+ assert topic.errors[:base].include?(ERROR_MESSAGE)
+ topic = Topic.new
+ assert topic.invalid?(:context2), "Validation does run on context2 when 'on' is set to context1 and context2"
+ assert topic.errors[:base].include?(ERROR_MESSAGE)
+ end
end

0 comments on commit 8855163

Please sign in to comment.