diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index d832027..7a292d3 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -161,34 +161,58 @@ module ActiveModel
end
end
- # Adds an error message (+messsage+) to the +attribute+, which will be returned on a call to on(attribute)
+ class FullErrorMessage < String
+ attr_reader :message
+ def initialize(message)
+ super((@message = message).to_s) # in case of symbols...
+ end
+
+ def full_message?
+ true
+ end
+ end
+
+ # Adds an error message (+message+) to the +attribute+, which will be returned on a call to on(attribute)
# for the same attribute and ensure that this error object returns false when asked if empty?. More than one
# error can be added to the same +attribute+ in which case an array will be returned on a call to on(attribute).
- # If no +messsage+ is supplied, :invalid is assumed.
- #
+ # If no +message+ is supplied, :invalid is assumed. Pass +:full_message => true+ in the options for specifying
+ # it is the full message, so that the attribute is not prepended in full_messages.
+ #
# 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 Time.now to be used within an error
def add(attribute, message = nil, options = {})
message ||= :invalid
message = generate_message(attribute, message, options) if message.is_a?(Symbol)
message = message.call if message.is_a?(Proc)
+ message = FullErrorMessage.new message if options[:full_message]
self[attribute] << message
end
+ def generate_full_message(attribute, message)
+ message = message.message if message.respond_to? :message
+ return (message.is_a?(Symbol) ? I18n.t(message) : message) if attribute == :base or (predicate.full_message? rescue false)
+
+ attr_name = attribute.to_s.gsub('.', '_').humanize
+ attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
+ options = { :default => "{{attribute}} {{message}}", :attribute => attr_name }
+
+ I18n.t(:"errors.format", options.merge(:message => message))
+ end
+
# Will add an error message to each of the attributes in +attributes+ that is empty.
- def add_on_empty(attributes, custom_message = nil)
+ def add_on_empty(attributes, custom_message = nil, options = {})
[attributes].flatten.each do |attribute|
value = @base.send(:read_attribute_for_validation, attribute)
is_empty = value.respond_to?(:empty?) ? value.empty? : false
- add(attribute, :empty, :default => custom_message) unless !value.nil? && !is_empty
+ add(attribute, :empty, options.merge(:default => custom_message)) unless !value.nil? && !is_empty
end
end
# Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?).
- def add_on_blank(attributes, custom_message = nil)
+ def add_on_blank(attributes, custom_message = nil, options = {})
[attributes].flatten.each do |attribute|
value = @base.send(:read_attribute_for_validation, attribute)
- add(attribute, :blank, :default => custom_message) if value.blank?
+ add(attribute, :blank, options.merge(:default => custom_message)) if value.blank?
end
end
@@ -206,20 +230,8 @@ module ActiveModel
full_messages = []
each do |attribute, messages|
- messages = Array(messages)
- next if messages.empty?
-
- if attribute == :base
- messages.each {|m| full_messages << m }
- else
- attr_name = attribute.to_s.gsub('.', '_').humanize
- attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
- options = { :default => "{{attribute}} {{message}}", :attribute => attr_name }
-
- messages.each do |m|
- full_messages << I18n.t(:"errors.format", options.merge(:message => m))
- end
- end
+ messages = Array.wrap(messages)
+ messages.each {|m| full_messages << generate_full_message(attribute, m)}
end
full_messages
diff --git a/activemodel/lib/active_model/validations/acceptance.rb b/activemodel/lib/active_model/validations/acceptance.rb
index 0423fcd..dcb8ef5 100644
--- a/activemodel/lib/active_model/validations/acceptance.rb
+++ b/activemodel/lib/active_model/validations/acceptance.rb
@@ -7,7 +7,7 @@ module ActiveModel
def validate_each(record, attribute, value)
unless value == options[:accept]
- record.errors.add(attribute, :accepted, :default => options[:message])
+ add_error(record, attribute, :accepted)
end
end
diff --git a/activemodel/lib/active_model/validations/confirmation.rb b/activemodel/lib/active_model/validations/confirmation.rb
index 8041d4b..aa170f3 100644
--- a/activemodel/lib/active_model/validations/confirmation.rb
+++ b/activemodel/lib/active_model/validations/confirmation.rb
@@ -4,7 +4,7 @@ module ActiveModel
def validate_each(record, attribute, value)
confirmed = record.send(:"#{attribute}_confirmation")
return if confirmed.nil? || value == confirmed
- record.errors.add(attribute, :confirmation, :default => options[:message])
+ add_error(record, attribute, :confirmation)
end
def setup(klass)
diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb
index 7ee718c..ebb67d8 100644
--- a/activemodel/lib/active_model/validations/exclusion.rb
+++ b/activemodel/lib/active_model/validations/exclusion.rb
@@ -8,7 +8,7 @@ module ActiveModel
def validate_each(record, attribute, value)
return unless options[:in].include?(value)
- record.errors.add(attribute, :exclusion, :default => options[:message], :value => value)
+ add_error(record, attribute, :exclusion, :value => value)
end
end
diff --git a/activemodel/lib/active_model/validations/format.rb b/activemodel/lib/active_model/validations/format.rb
index 9a9e7ec..b8dc3ff 100644
--- a/activemodel/lib/active_model/validations/format.rb
+++ b/activemodel/lib/active_model/validations/format.rb
@@ -2,11 +2,8 @@ module ActiveModel
module Validations
class FormatValidator < EachValidator
def validate_each(record, attribute, value)
- if options[:with] && value.to_s !~ options[:with]
- record.errors.add(attribute, :invalid, :default => options[:message], :value => value)
- elsif options[:without] && value.to_s =~ options[:without]
- record.errors.add(attribute, :invalid, :default => options[:message], :value => value)
- end
+ add_error(record, attribute, :invalid, :value => value) if
+ (options[:with] && value.to_s !~ options[:with]) or (options[:without] && value.to_s =~ options[:without])
end
def check_validity!
diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb
index 0c1334f..9f19d36 100644
--- a/activemodel/lib/active_model/validations/inclusion.rb
+++ b/activemodel/lib/active_model/validations/inclusion.rb
@@ -8,7 +8,7 @@ module ActiveModel
def validate_each(record, attribute, value)
return if options[:in].include?(value)
- record.errors.add(attribute, :inclusion, :default => options[:message], :value => value)
+ add_error(record, attribute, :inclusion, :value => value)
end
end
diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb
index 9ceb754..cdbae7f 100644
--- a/activemodel/lib/active_model/validations/length.rb
+++ b/activemodel/lib/active_model/validations/length.rb
@@ -37,7 +37,7 @@ module ActiveModel
CHECKS.each do |key, validity_check|
next unless check_value = options[key]
- custom_message = options[:message] || options[MESSAGES[key]]
+ custom_message = message || options[MESSAGES[key]]
valid_value = if key == :maximum
value.nil? || value.size.send(validity_check, check_value)
@@ -46,7 +46,7 @@ module ActiveModel
end
next if valid_value
- record.errors.add(attribute, MESSAGES[key], :default => custom_message, :count => check_value)
+ add_error(record, attribute, MESSAGES[key], :default => custom_message, :count => check_value)
end
end
end
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index c6d84c5..99448b3 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -26,7 +26,7 @@ module ActiveModel
return if options[:allow_nil] && raw_value.nil?
unless value = parse_raw_value(raw_value, options)
- record.errors.add(attr_name, :not_a_number, :value => raw_value, :default => options[:message])
+ add_error(record, attr_name, :not_a_number, :value => raw_value)
return
end
@@ -34,14 +34,14 @@ module ActiveModel
case option
when :odd, :even
unless value.to_i.send(CHECKS[option])
- record.errors.add(attr_name, option, :value => value, :default => options[:message])
+ add_error(record, attr_name, option, :value => value)
end
else
option_value = option_value.call(record) if option_value.is_a?(Proc)
option_value = record.send(option_value) if option_value.is_a?(Symbol)
unless value.send(CHECKS[option], option_value)
- record.errors.add(attr_name, option, :default => options[:message], :value => value, :count => option_value)
+ add_error(record, attr_name, option, :value => value, :count => option_value)
end
end
end
diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb
index 4a71cf7..624c88e 100644
--- a/activemodel/lib/active_model/validations/presence.rb
+++ b/activemodel/lib/active_model/validations/presence.rb
@@ -4,7 +4,7 @@ module ActiveModel
module Validations
class PresenceValidator < EachValidator
def validate(record)
- record.errors.add_on_blank(attributes, options[:message])
+ add_on_blank_error record
end
end
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index b61f0cb..57452de 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -158,6 +158,21 @@ module ActiveModel #:nodoc:
# ArgumentError when invalid options are supplied.
def check_validity!
end
+
+ def message
+ options[:full_message] || options[:message]
+ end
+
+ def add_error(record, attribute, error_message, error_options={})
+ opts = {:default => message}
+ opts.merge! :full_message => !!options[:full_message] if options[:full_message]
+ record.errors.add(attribute, error_message, opts.merge(error_options))
+ end
+
+ def add_on_blank_error(record)
+ opts = options[:full_message] ? {:full_message => true} : {}
+ record.errors.add_on_blank attributes, message, opts
+ end
end
# BlockValidator is a special EachValidator which receives a block on initialization