Class: DataMapper::Validations::ContextualValidators

### Home Classes Methods

### In Files

- lib/dm-validations/contextual_validators.rb

### Parent

Object

### Methods

- ::new
- #add
- #assert_valid
- #attribute
- #clear!
- #context
- #current_context
- #execute
- #load_validated_properties
- #normalize_options
- #valid_context?

### Included Modules

- Enumerable

### Files

- LICENSE
- README.rdoc

### Class/Module Index

Quicksearch

- DataMapper
- DataMapper::InvalidContextError
- DataMapper::Validate
- DataMapper::ValidationError
- DataMapper::Validations
- DataMapper::Validations::AbsenceValidator
- DataMapper::Validations::AcceptanceValidator
- DataMapper::Validations::AutoValidations
- DataMapper::Validations::AutoValidations::ModelExtension
- DataMapper::Validations::ClassMethods
- DataMapper::Validations::ConfirmationValidator
- DataMapper::Validations::Context
- DataMapper::Validations::ContextualValidators
- DataMapper::Validations::Format
- DataMapper::Validations::Format::Email
- DataMapper::Validations::Format::Url
- DataMapper::Validations::FormatValidator
- DataMapper::Validations::GenericValidator
- DataMapper::Validations::LengthValidator
- DataMapper::Validations::MethodValidator
- DataMapper::Validations::NumericalityValidator
- DataMapper::Validations::OrderedHash
- DataMapper::Validations::PresenceValidator
- DataMapper::Validations::PrimitiveTypeValidator
- DataMapper::Validations::UniquenessValidator
- DataMapper::Validations::UnknownValidationFormat
- DataMapper::Validations::ValidatesAbsence
- DataMapper::Validations::ValidatesAcceptance
- DataMapper::Validations::ValidatesConfirmation
- DataMapper::Validations::ValidatesFormat
- DataMapper::Validations::ValidatesLength
- DataMapper::Validations::ValidatesNumericality
- DataMapper::Validations::ValidatesPresence
- DataMapper::Validations::ValidatesPrimitiveType
- DataMapper::Validations::ValidatesUniqueness
- DataMapper::Validations::ValidatesWithBlock
- DataMapper::Validations::ValidatesWithMethod
- DataMapper::Validations::ValidatesWithin
- DataMapper::Validations::ValidationErrors
- DataMapper::Validations::WithinValidator
- Object

No matching classes.

# DataMapper::Validations::ContextualValidators

@author Guy van den Berg @since 0.9

### Attributes

attributes[R]
contexts[R]

### Public Class Methods

new(model = nil) click to toggle source

    # File lib/dm-validations/contextual_validators.rb, line 21
    def initialize(model = nil)
      @model      = model
      @contexts   = {}
      @attributes = {}
    end

### Public Instance Methods

add(validator_class, *attributes) click to toggle source

Create a new validator of the given klazz and push it onto the requested context for each of the attributes in `attributes`

@param [DataMapper::Validations::GenericValidator] validator_class

    Validator class, example: DataMapper::Validations::LengthValidator

@param [Array<Symbol>] attributes

    Attribute names given to validation macro, example:
    [:first_name, :last_name] in validates_presence_of :first_name, :last_name

@param [Hash] options

    Options supplied to validation macro, example:
    {:context=>:default, :maximum=>50, :allow_nil=>true, :message=>nil}

@option [Symbol] :context

    the context in which the new validator should be run

@option [Boolean] :allow_nil

    whether or not the new validator should allow nil values

@option [Boolean] :message

    the error message the new validator will provide on validation failure

    # File lib/dm-validations/contextual_validators.rb, line 78
    def add(validator_class, *attributes)
      options = attributes.last.kind_of?(Hash) ? attributes.pop.dup : {}
      normalize_options(options)
      validator_options = DataMapper::Ext::Hash.except(options, :context)

      attributes.each do |attribute|
        # TODO: is :context part of the Validator state (ie, intrinsic),
        # or is it just membership in a collection?
        validator = validator_class.new(attribute, validator_options)
        attribute_validators = self.attribute(attribute)
        attribute_validators << validator unless attribute_validators.include?(validator)

        options[:context].each do |context|
          context_validators = self.context(context)
          next if context_validators.include?(validator)
          context_validators << validator
          # TODO: eliminate this, then eliminate the @model ivar entirely
          Validations::ClassMethods.create_context_instance_methods(@model, context) if @model
        end
      end
    end

assert_valid(context) click to toggle source

Assert that the given context is valid for this model

@param [Symbol] context

    the context to test

@raise [InvalidContextError]

    raised if the context is not valid for this model

@api private

TODO: is this method actually needed?

    # File lib/dm-validations/contextual_validators.rb, line 172
    def assert_valid(context)
      unless valid_context?(context)
        raise InvalidContextError, "#{context} is an invalid context, known contexts are #{contexts.keys.inspect}"
      end
    end

attribute(name) click to toggle source

Return an array of validators for a named property

@param [Symbol]

    Property name for which to return validators

@return [Array<DataMapper::Validations::GenericValidator>]

    An array of validators bound to the given property

    # File lib/dm-validations/contextual_validators.rb, line 47
    def attribute(name)
      attributes[name] ||= OrderedSet.new
    end

clear!() click to toggle source

Clear all named context validators off of the resource

    # File lib/dm-validations/contextual_validators.rb, line 53
    def clear!
      contexts.clear
      attributes.clear
    end

context(name) click to toggle source

Return an array of validators for a named context

@param [String]

    Context name for which to return validators

@return [Array<DataMapper::Validations::GenericValidator>]

    An array of validators bound to the given context

    # File lib/dm-validations/contextual_validators.rb, line 37
    def context(name)
      contexts[name] ||= OrderedSet.new
    end

current_context() click to toggle source

Returns the current validation context on the stack if valid for this model, nil if no contexts are defined for the model (and no contexts are on the validation stack), or :default if the current context is invalid for this model or no contexts have been defined for this model and no context is on the stack.

@return [Symbol]

    the current validation context from the stack (if valid for this model),
    nil if no context is on the stack and no contexts are defined for this model,
    or :default if the context on the stack is invalid for this model or
    no context is on the stack and this model has at least one validation context

@api private

TODO: simplify the semantics of current_context, valid?

    # File lib/dm-validations/contextual_validators.rb, line 141
    def current_context
      context = Validations::Context.current
      valid_context?(context) ? context : :default
    end

execute(named_context, target) click to toggle source

Execute all validators in the named context against the target. Load together any properties that are designated lazy but are not yet loaded.

@param [Symbol] named_context

    the context we are validating against

@param [Object] target

    the resource that we are validating

@return [Boolean]

    true if all are valid, otherwise false

    # File lib/dm-validations/contextual_validators.rb, line 188
    def execute(named_context, target)
      target.errors.clear!

      available_validators  = context(named_context)
      executable_validators = available_validators.select { |v| v.execute?(target) }

      # In the case of a new Resource or regular ruby class instance,
      # everything needs to be validated completely, and no eager-loading
      # logic should apply.
      #
      if target.kind_of?(DataMapper::Resource) && !target.new?
        load_validated_properties(target, executable_validators)
      end
      executable_validators.map { |validator| validator.call(target) }.all?
    end

load_validated_properties(resource, validators) click to toggle source

Load all lazy, not-yet-loaded properties that need validation, all at once.

    # File lib/dm-validations/contextual_validators.rb, line 206
    def load_validated_properties(resource, validators)
      properties = resource.model.properties

      properties_to_load = validators.map { |validator|
        properties[validator.field_name]
      }.compact.select { |property|
        property.lazy? && !property.loaded?(resource)
      }

      resource.__send__(:eager_load, properties_to_load)
    end

normalize_options(options, defaults = nil) click to toggle source

Clean up the argument list and return a opts hash, including the merging of any default opts. Set the context to default if none is provided. Also allow :context to be aliased to :on, :when & :group

@param [Hash] options

    the options to be normalized

@param [NilClass, Hash] defaults

    default keys/values to set on normalized options

@return [Hash]

    the normalized options

@api private

    # File lib/dm-validations/contextual_validators.rb, line 113
    def normalize_options(options, defaults = nil)
      context = [
        options.delete(:group),
        options.delete(:on),
        options.delete(:when),
        options.delete(:context)
      ].compact.first

      options[:context] = Array(context || :default)
      options.update(defaults) unless defaults.nil?
      options
    end

valid_context?(context) click to toggle source

Test if the context is valid for the model

@param [Symbol] context

    the context to test

@return [Boolean]

    true if the context is valid for the model

@api private

TODO: investigate removing the `contexts.empty?` test here.

    # File lib/dm-validations/contextual_validators.rb, line 157
    def valid_context?(context)
      contexts.empty? || contexts.include?(context)
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.