Improve support for non Active Record objects on `validates_associated`

Skipping `marked_for_destruction?` when the associated object does not responds
to it make easier to validate virtual associations built on top of Active Model
objects and/or serialized objects that implement a `valid?` instance method.
This commit is contained in:
Kassio Borges 2015-11-08 10:57:25 -02:00
parent 25673f47b6
commit c8bbe9aefa
3 changed files with 28 additions and 2 deletions

View File

@ -1,3 +1,11 @@
* Improve support for non Active Record objects on `validates_associated`
Skipping `marked_for_destruction?` when the associated object does not responds
to it make easier to validate virtual associations built on top of Active Model
objects and/or serialized objects that implement a `valid?` instance method.
*Kassio Borges*, *Lucas Mazza*
* Change connection management middleware to return a new response with
a body proxy, rather than mutating the original.

View File

@ -2,10 +2,16 @@ module ActiveRecord
module Validations
class AssociatedValidator < ActiveModel::EachValidator #:nodoc:
def validate_each(record, attribute, value)
if Array.wrap(value).reject {|r| r.marked_for_destruction? || r.valid?}.any?
record.errors.add(attribute, :invalid, options.merge(:value => value))
if Array(value).reject { |r| valid_object?(r) }.any?
record.errors.add(attribute, :invalid, options.merge(value: value))
end
end
private
def valid_object?(record)
(record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid?
end
end
module ClassMethods

View File

@ -45,6 +45,18 @@ class AssociationValidationTest < ActiveRecord::TestCase
assert t.valid?
end
def test_validates_associated_without_marked_for_destruction
reply = Class.new do
def valid?
true
end
end
Topic.validates_associated(:replies)
t = Topic.new
t.define_singleton_method(:replies) { [reply.new] }
assert t.valid?
end
def test_validates_associated_with_custom_message_using_quotes
Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
Topic.validates_presence_of :content