aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/CHANGELOG2
-rw-r--r--activemodel/lib/active_model/errors.rb42
-rw-r--r--activemodel/lib/active_model/secure_password.rb4
-rw-r--r--activemodel/test/cases/errors_test.rb64
-rw-r--r--activemodel/test/cases/secure_password_test.rb10
5 files changed, 103 insertions, 19 deletions
diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG
index 3d26d646b0..bf077bef35 100644
--- a/activemodel/CHANGELOG
+++ b/activemodel/CHANGELOG
@@ -1,3 +1,5 @@
+* Added ActiveModel::Errors#added? to check if a specific error has been added [Martin Svalin]
+
* Add ability to define strict validation(with :strict => true option) that always raises exception when fails [Bogdan Gusiev]
* Deprecate "Model.model_name.partial_path" in favor of "model.to_partial_path" [Grant Hutchins, Peter Jaros]
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 6db3ca7340..8337b04c0d 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -212,13 +212,7 @@ module ActiveModel
# If +message+ is a symbol, it will be translated using the appropriate scope (see +translate_error+).
# If +message+ is a proc, it will be called, allowing for things like <tt>Time.now</tt> to be used within an error.
def add(attribute, message = nil, options = {})
- message ||= :invalid
-
- if message.is_a?(Symbol)
- message = generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))
- elsif message.is_a?(Proc)
- message = message.call
- end
+ message = normalize_message(attribute, message, options)
if options[:strict]
raise ActiveModel::StrictValidationFailed, message
end
@@ -243,6 +237,15 @@ module ActiveModel
end
end
+ # Returns true if an error on the attribute with the given message is present, false otherwise.
+ # +message+ is treated the same as for +add+.
+ # p.errors.add :name, :blank
+ # p.errors.added? :name, :blank # => true
+ def added?(attribute, message = nil, options = {})
+ message = normalize_message(attribute, message, options)
+ self[attribute].include? message
+ end
+
# Returns all the full error messages in an array.
#
# class Company
@@ -299,13 +302,17 @@ module ActiveModel
def generate_message(attribute, type = :invalid, options = {})
type = options.delete(:message) if options[:message].is_a?(Symbol)
- defaults = @base.class.lookup_ancestors.map do |klass|
- [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
- :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ]
+ if @base.class.respond_to?(:i18n_scope)
+ defaults = @base.class.lookup_ancestors.map do |klass|
+ [ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.attributes.#{attribute}.#{type}",
+ :"#{@base.class.i18n_scope}.errors.models.#{klass.model_name.i18n_key}.#{type}" ]
+ end
+ else
+ defaults = []
end
defaults << options.delete(:message)
- defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}"
+ defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" if @base.class.respond_to?(:i18n_scope)
defaults << :"errors.attributes.#{attribute}.#{type}"
defaults << :"errors.messages.#{type}"
@@ -324,6 +331,19 @@ module ActiveModel
I18n.translate(key, options)
end
+
+ private
+ def normalize_message(attribute, message, options)
+ message ||= :invalid
+
+ if message.is_a?(Symbol)
+ generate_message(attribute, message, options.except(*CALLBACKS_OPTIONS))
+ elsif message.is_a?(Proc)
+ message.call
+ else
+ message
+ end
+ end
end
class StrictValidationFailed < StandardError
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 7a109d9a52..db78864c67 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -32,8 +32,8 @@ module ActiveModel
# User.find_by_name("david").try(:authenticate, "notright") # => nil
# User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
def has_secure_password
- # Load bcrypt-ruby only when has_secured_password is used to avoid make ActiveModel
- # (and by extension the entire framework) dependent on a binary library.
+ # Load bcrypt-ruby only when has_secure_password is used.
+ # This is to avoid ActiveModel (and by extension the entire framework) being dependent on a binary library.
gem 'bcrypt-ruby', '~> 3.0.0'
require 'bcrypt'
diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb
index 4c76bb43a8..8ddedb160a 100644
--- a/activemodel/test/cases/errors_test.rb
+++ b/activemodel/test/cases/errors_test.rb
@@ -66,6 +66,63 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal ["can not be blank"], person.errors[:name]
end
+ test "should be able to add an error with a symbol" do
+ person = Person.new
+ person.errors.add(:name, :blank)
+ message = person.errors.generate_message(:name, :blank)
+ assert_equal [message], person.errors[:name]
+ end
+
+ test "should be able to add an error with a proc" do
+ person = Person.new
+ message = Proc.new { "can not be blank" }
+ person.errors.add(:name, message)
+ assert_equal ["can not be blank"], person.errors[:name]
+ end
+
+ test "added? should be true if that error was added" do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ assert person.errors.added?(:name, "can not be blank")
+ end
+
+ test "added? should handle when message is a symbol" do
+ person = Person.new
+ person.errors.add(:name, :blank)
+ assert person.errors.added?(:name, :blank)
+ end
+
+ test "added? should handle when message is a proc" do
+ person = Person.new
+ message = Proc.new { "can not be blank" }
+ person.errors.add(:name, message)
+ assert person.errors.added?(:name, message)
+ end
+
+ test "added? should default message to :invalid" do
+ person = Person.new
+ person.errors.add(:name, :invalid)
+ assert person.errors.added?(:name)
+ end
+
+ test "added? should be true when several errors are present, and we ask for one of them" do
+ person = Person.new
+ person.errors.add(:name, "can not be blank")
+ person.errors.add(:name, "is invalid")
+ assert person.errors.added?(:name, "can not be blank")
+ end
+
+ test "added? should be false if no errors are present" do
+ person = Person.new
+ assert !person.errors.added?(:name)
+ end
+
+ test "added? should be false when an error is present, but we check for another error" do
+ person = Person.new
+ person.errors.add(:name, "is invalid")
+ assert !person.errors.added?(:name, "can not be blank")
+ end
+
test 'should respond to size' do
person = Person.new
person.errors.add(:name, "can not be blank")
@@ -112,5 +169,12 @@ class ErrorsTest < ActiveModel::TestCase
assert_equal ["is invalid"], hash[:email]
end
+ test "generate_message should work without i18n_scope" do
+ person = Person.new
+ assert !Person.respond_to?(:i18n_scope)
+ assert_nothing_raised {
+ person.errors.generate_message(:name, :blank)
+ }
+ end
end
diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb
index 6950c3be1f..4338a3fc53 100644
--- a/activemodel/test/cases/secure_password_test.rb
+++ b/activemodel/test/cases/secure_password_test.rb
@@ -10,15 +10,13 @@ class SecurePasswordTest < ActiveModel::TestCase
end
test "blank password" do
- user = User.new
- user.password = ''
- assert !user.valid?, 'user should be invalid'
+ @user.password = ''
+ assert !@user.valid?, 'user should be invalid'
end
test "nil password" do
- user = User.new
- user.password = nil
- assert !user.valid?, 'user should be invalid'
+ @user.password = nil
+ assert !@user.valid?, 'user should be invalid'
end
test "password must be present" do