Class: Mongoid::Validatable::AssociatedValidator
Relationships & Source Files | |
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
ActiveModel::Validator
|
|
Instance Chain:
self,
ActiveModel::Validator
|
|
Inherits: |
ActiveModel::Validator
|
Defined in: | lib/mongoid/validatable/associated.rb |
Overview
Validates whether or not an association is valid or not. Will correctly handle has one and has many associations.
Instance Method Summary
-
#attributes
Required by
validates_with
so that the validator gets added to the correct attributes. -
#validate(document)
Checks that the named associations of the given record (‘attributes`) are valid.
-
#get_target_documents(target) ⇒ Array<Mongoid::Document>
private
Examine the given target object and return an array of documents (possibly empty) that the target represents.
-
#get_target_documents_for_has_many(target) ⇒ Array<Mongoid::Document>
private
Returns the list of all currently in-memory values held by the target.
-
#get_target_documents_for_other(target) ⇒ Array<Mongoid::Document>
private
Returns the target as an array.
-
#validate_association(document, attribute)
private
Validates that the given association provided is either nil, persisted and unchanged, or invalid.
Instance Method Details
#attributes
Required by validates_with
so that the validator gets added to the correct attributes.
# File 'lib/mongoid/validatable/associated.rb', line 22
def attributes [:attributes] end
#get_target_documents(target) ⇒ Array<Mongoid::Document> (private)
Examine the given target object and return an array of documents (possibly empty) that the target represents.
# File 'lib/mongoid/validatable/associated.rb', line 97
def get_target_documents(target) if target.respond_to?(:_loaded?) get_target_documents_for_has_many(target) else get_target_documents_for_other(target) end end
#get_target_documents_for_has_many(target) ⇒ Array<Mongoid::Document> (private)
Returns the list of all currently in-memory values held by the target. The target will not be loaded.
# File 'lib/mongoid/validatable/associated.rb', line 113
def get_target_documents_for_has_many(target) [ *target._loaded.values, *target._added.values ] end
#get_target_documents_for_other(target) ⇒ Array<Mongoid::Document> (private)
Returns the target as an array. If the target represents a single value, it is wrapped in an array.
# File 'lib/mongoid/validatable/associated.rb', line 124
def get_target_documents_for_other(target) Array.wrap(target) end
#validate(document)
Checks that the named associations of the given record (‘attributes`) are valid. This does NOT load the associations from the database, and will only validate records that are dirty or unpersisted.
If anything is not valid, appropriate errors will be added to the document
parameter.
# File 'lib/mongoid/validatable/associated.rb', line 36
def validate(document) [:attributes].each do |attr_name| validate_association(document, attr_name) end end
#validate_association(document, attribute) (private)
Validates that the given association provided is either nil, persisted and unchanged, or invalid. Otherwise, the appropriate errors will be added to the parent document.
# File 'lib/mongoid/validatable/associated.rb', line 50
def validate_association(document, attribute) # grab the proxy from the instance variable directly; we don't want # any loading logic to run; we just want to see if it's already # been loaded. proxy = document.ivar(attribute) return unless proxy # if the variable exists, now we see if it is a proxy, or an actual # document. It might be a literal document instead of a proxy if this # document was created with a Document instance as a provided attribute, # e.g. "Post.new(message: Message.new)". target = proxy.respond_to?(:_target) ? proxy._target : proxy # Now, fetch the list of documents from the target. Target may be a # single value, or a list of values, and in the case of HasMany, # might be a rather complex collection. We need to do this without # triggering a load, so it's a bit of a delicate dance. list = get_target_documents(target) valid = document.validating do # Now, treating the target as an array, look at each element # and see if it is valid, but only if it has already been # persisted, or changed, and hasn't been flagged for destroy. # # use map.all? instead of just all?, because all? will do short-circuit # evaluation and terminate on the first failed validation. list.map do |value| if value && !value.flagged_for_destroy? && (!value.persisted? || value.changed?) value.validated? ? true : value.valid? else true end end.all? end document.errors.add(attribute, :invalid) unless valid end