From 2bd61cb09aa90e9bdd42835f8e0f79c8770e73a8 Mon Sep 17 00:00:00 2001 From: Aaron Lasseigne Date: Sun, 10 Feb 2019 10:41:41 -0600 Subject: [PATCH] fix #435, allow for the `:message` option when adding an error --- lib/active_interaction/errors.rb | 70 +++++++++++++------------- spec/active_interaction/errors_spec.rb | 15 ++++++ 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/lib/active_interaction/errors.rb b/lib/active_interaction/errors.rb index 45754e19..7540d5b2 100644 --- a/lib/active_interaction/errors.rb +++ b/lib/active_interaction/errors.rb @@ -96,60 +96,62 @@ class Errors < ActiveModel::Errors # # @return [Errors] def merge!(other) - if other.respond_to?(:details) - merge_details!(other) - else - merge_messages!(other) - end + if other.respond_to?(:details) + merge_details!(other) + else + merge_messages!(other) + end - self + self end private + def attribute?(attribute) + @base.respond_to?(attribute) + end + + def detailed_error?(detail) + detail[:error].is_a?(Symbol) + end + def merge_messages!(other) other.messages.each do |attribute, messages| messages.each do |message| - unless attribute?(attribute) - message = full_message(attribute, message) - attribute = :base - end - add(attribute, message) unless added?(attribute, message) + merge_message!(attribute, message) end end end - def merge_details!(other) - other.details.each do |attribute, details| - details.each do |detail| - detail = detail.dup - error = detail.delete(:error) - - merge_detail!(other, attribute, detail, error) - end + def merge_message!(attribute, message) + unless attribute?(attribute) + message = full_message(attribute, message) + attribute = :base end + add(attribute, message) unless added?(attribute, message) end - def merge_detail!(other, attribute, detail, error) - if attribute?(attribute) || attribute == :base - add(attribute, error, detail) unless added?(attribute, error, detail) - else - translated_error = translate(other, attribute, error, detail) - message = full_message(attribute, translated_error) - attribute = :base - add(attribute, message) unless added?(attribute, message) + def merge_details!(other) + other.messages.each do |attribute, messages| + messages.zip(other.details[attribute]) do |message, detail| + if detailed_error?(detail) + merge_detail!(attribute, detail, message) + else + merge_message!(attribute, message) + end + end end end - def attribute?(attribute) - @base.respond_to?(attribute) - end + def merge_detail!(attribute, detail, message) + if attribute?(attribute) || attribute == :base + options = detail.dup + error = options.delete(:error) + options[:message] = message - def translate(other, attribute, error, detail) - if error.is_a?(Symbol) - other.generate_message(attribute, error, detail) + add(attribute, error, options) unless added?(attribute, error, options) else - error + merge_message!(attribute, message) end end end diff --git a/spec/active_interaction/errors_spec.rb b/spec/active_interaction/errors_spec.rb index 69f6c2d5..57714c4a 100644 --- a/spec/active_interaction/errors_spec.rb +++ b/spec/active_interaction/errors_spec.rb @@ -91,6 +91,21 @@ def self.name expect(errors.details[:base]).to eql [{ error: message }] end end + + context 'that uses the :message option' do + let(:message) { SecureRandom.hex } + let(:error_name) { :some_error } + + before do + other.add(:base, error_name, message: message) + end + + it 'adds the error' do + errors.merge!(other) + expect(errors.details[:base]).to eql [{ error: error_name }] + expect(errors.messages[:base]).to eql [message] + end + end end context 'with an interpolated detailed error' do