diff --git a/lib/validates_associated_with_context/associated_with_context.rb b/lib/validates_associated_with_context/associated_with_context.rb index 9d8c06d..b2851e7 100644 --- a/lib/validates_associated_with_context/associated_with_context.rb +++ b/lib/validates_associated_with_context/associated_with_context.rb @@ -2,20 +2,45 @@ module ValidatesAssociatedWithContext class AssociatedWithContextValidator < ActiveModel::EachValidator # :nodoc: - attr_reader :context, :inherit_context + attr_reader :inherit_context, :bubble_messages def initialize(options) @context = options.delete(:context) @inherit_context = options.delete(:inherit_context) + @bubble_messages = options.delete(:bubble_messages) super end - def validate_each(record, attribute, value) - validation_context = inherit_context ? record.validation_context : context + def context(record) + return record.validation_context if inherit_context - if Array(value).reject { |r| valid_object?(r, validation_context) }.any? - record.errors.add(attribute, :invalid, **options.merge(value: value)) + if @context.respond_to?(:call) + @context.call record + else + @context + end + end + + def validate_each(record, attribute, value) + validation_context = context(record) + + if bubble_messages + Array(value).each do |r| + next if valid_object?(r, validation_context) + + if r.errors.any? + r.errors.each do |error| + record.errors.add(attribute, error.full_message, **options.merge(value: r)) + end + else + record.errors.add(attribute, :invalid, **options.merge(value: r)) + end + end + else + if Array(value).reject { |r| valid_object?(r, validation_context) }.any? + record.errors.add(attribute, :invalid, **options.merge(value: value)) + end end end