aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activemodel/CHANGELOG.md2
-rw-r--r--activemodel/lib/active_model/errors.rb8
-rw-r--r--activemodel/lib/active_model/validations/validates.rb7
-rw-r--r--activemodel/test/cases/validations_test.rb9
-rw-r--r--guides/source/active_record_validations_callbacks.textile10
5 files changed, 32 insertions, 4 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md
index 847ae7f237..b9966cb2fa 100644
--- a/activemodel/CHANGELOG.md
+++ b/activemodel/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* `AM::Validation#validates` ability to pass custom exception to `:strict` option *Bogdan Gusiev*
+
* Changed `AM::Serializers::JSON.include_root_in_json' default value to false.
Now, AM Serializers and AR objects have the same default behaviour. Fixes #6578.
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 1026b0f4d3..b3b9ba8e56 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -283,15 +283,19 @@ module ActiveModel
#
# If the <tt>:strict</tt> option is set to true will raise
# ActiveModel::StrictValidationFailed instead of adding the error.
+ # <tt>:strict</tt> option can also be set to any other exception.
#
# person.errors.add(:name, nil, strict: true)
# # => ActiveModel::StrictValidationFailed: name is invalid
+ # person.errors.add(:name, nil, strict: NameIsInvalid)
+ # # => NameIsInvalid: name is invalid
#
# person.errors.messages # => {}
def add(attribute, message = nil, options = {})
message = normalize_message(attribute, message, options)
- if options[:strict]
- raise ActiveModel::StrictValidationFailed, full_message(attribute, message)
+ if exception = options[:strict]
+ exception = ActiveModel::StrictValidationFailed if exception == true
+ raise exception, full_message(attribute, message)
end
self[attribute] << message
diff --git a/activemodel/lib/active_model/validations/validates.rb b/activemodel/lib/active_model/validations/validates.rb
index 5892ad29d1..eb6e604851 100644
--- a/activemodel/lib/active_model/validations/validates.rb
+++ b/activemodel/lib/active_model/validations/validates.rb
@@ -84,12 +84,15 @@ module ActiveModel
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The
# method, proc or string should return or evaluate to a +true+ or
# +false+ value.
- # * <tt>:strict</tt> - Specifies whether validation should be strict.
- # See <tt>ActiveModel::Validation#validates!</tt> for more information.
+ # * <tt>:strict</tt> - if the <tt>:strict</tt> option is set to true
+ # will raise ActiveModel::StrictValidationFailed instead of adding the error.
+ # <tt>:strict</tt> option can also be set to any other exception.
#
# Example:
#
# validates :password, presence: true, confirmation: true, if: :password_required?
+ # validates :token, uniqueness: true, strict: TokenGenerationException
+ #
#
# Finally, the options +:if+, +:unless+, +:on+, +:allow_blank+, +:allow_nil+
# and +:strict+ can be given to one specific validator, as a hash:
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index 8ea9745fbf..a9d32808da 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -11,6 +11,8 @@ require 'active_support/xml_mini'
class ValidationsTest < ActiveModel::TestCase
+ class CustomStrictValidationException < StandardError; end
+
def setup
Topic._validators.clear
end
@@ -323,6 +325,13 @@ class ValidationsTest < ActiveModel::TestCase
end
end
+ def test_strict_validation_custom_exception
+ Topic.validates_presence_of :title, :strict => CustomStrictValidationException
+ assert_raises CustomStrictValidationException do
+ Topic.new.valid?
+ end
+ end
+
def test_validates_with_bang
Topic.validates! :title, :presence => true
assert_raises ActiveModel::StrictValidationFailed do
diff --git a/guides/source/active_record_validations_callbacks.textile b/guides/source/active_record_validations_callbacks.textile
index cf7293bd9e..b866337e3f 100644
--- a/guides/source/active_record_validations_callbacks.textile
+++ b/guides/source/active_record_validations_callbacks.textile
@@ -532,6 +532,16 @@ end
Person.new.valid? => ActiveModel::StrictValidationFailed: Name can't be blank
</ruby>
+There is also an ability to pass custom exception to +:strict+ option
+
+<ruby>
+class Person < ActiveRecord::Base
+ validates :token, :presence => true, :uniqueness => true, :strict => TokenGenerationException
+end
+
+Person.new.valid? => TokenGenerationException: Token can't be blank
+</ruby>
+
h3. Conditional Validation
Sometimes it will make sense to validate an object just when a given predicate is satisfied. You can do that by using the +:if+ and +:unless+ options, which can take a symbol, a string, a +Proc+ or an +Array+. You may use the +:if+ option when you want to specify when the validation *should* happen. If you want to specify when the validation *should not* happen, then you may use the +:unless+ option.