diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index 1431228..96015d8 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -170,6 +170,16 @@ module ActiveModel self end + # Represents a full error message + class ErrorMessage < String + attr_reader :full_message + + def initialize(message, full_message) + super(message || full_message) + @full_message = full_message + end + end + # Adds +message+ to the error messages on +attribute+, which will be returned on a call to # on(attribute) for the same attribute. 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). @@ -178,15 +188,19 @@ 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 Time.now 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 + messages = {:message => message || :invalid, :full_message => options[:full_message]} + options = options.except(*CALLBACKS_OPTIONS) + + messages.each do |type, message| + if message.is_a? Symbol + messages[type] = generate_message(attribute, message, options) + elsif message.is_a? Proc + messages[type] = message.call + end end - self[attribute] << message + self[attribute] << (!messages[:full_message] ? messages[:message] : + ErrorMessage.new(messages[:message], messages[:full_message])) end # Will add an error message to each of the attributes in +attributes+ that is empty. @@ -245,7 +259,8 @@ module ActiveModel options = { :default => "%{attribute} %{message}", :attribute => attr_name } messages.each do |m| - full_messages << I18n.t(:"errors.format", options.merge(:message => m)) + full_messages << ((m.respond_to?(:full_message) && m.full_message) ? + m.full_message : I18n.t(:"errors.format", options.merge(:message => m))) end end end @@ -280,6 +295,7 @@ module ActiveModel # def generate_message(attribute, type = :invalid, options = {}) type = options.delete(:message) if options[:message].is_a?(Symbol) + full_message = options.delete(:full_message) if options[:default] ActiveSupport::Deprecation.warn \ @@ -296,7 +312,7 @@ module ActiveModel defaults << options.delete(:message) defaults << :"#{@base.class.i18n_scope}.errors.messages.#{type}" defaults << :"errors.attributes.#{attribute}.#{type}" - defaults << :"errors.messages.#{type}" + defaults << :"errors.#{full_message ? 'full_' : ''}messages.#{type}" defaults.compact! defaults.flatten!