Class: Ward::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/ward/validator.rb

Overview

Pairs a context (or chain) with a matcher.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context, matcher, options = {}) ⇒ Validator

Creates a new Validator.

Parameters:

  • context (Ward::ContextChain, Ward::Context)

    The context to be used to fetch the value for the matcher.

  • matcher (Ward::Matchers::Matcher)

    A matcher to be used to validate the context value.

  • options (Hash) (defaults to: {})

    Extra options used to customise the Validator.

Options Hash (options):

  • :scenarios (Symbol, Array<Symbol>)

    An array of scenarios in which this validator should be run

  • :message (Hash{Symbol => String}, String)

    The error message to be used if the validator fails (see DSL::ValidationBuilder#message).

  • :context_name (String)

    The name to be used for the context when generating error messages.



55
56
57
58
59
60
61
# File 'lib/ward/validator.rb', line 55

def initialize(context, matcher, options = {})
  @context, @matcher = context, matcher
  @scenarios = Array(options[:scenarios] || :default).freeze
  @negative = options[:negative] || false
  @message  = options[:message].freeze
  @context_name = options[:context_name].freeze
end

Instance Attribute Details

#contextWard::ContextChain, Ward::Context (readonly)

Returns the context.



10
11
12
# File 'lib/ward/validator.rb', line 10

def context
  @context
end

#matcherWard::Matchers::Matcher (readonly)

Returns the matcher.



16
17
18
# File 'lib/ward/validator.rb', line 16

def matcher
  @matcher
end

#messageHash, ... (readonly)

An override to the default message.

If set, this message will always be used if the validation fails, regardless of whether it is used as a positive or negative assertion.

Returns:

  • (Hash, String, nil)

    Returns a Hash if the user wishes to use a different message depending on the error state of the matcher (certain matchers, like Has, return a different error depending on what went wrong), a String if an explicit error message is set, or nil if no error message is set (in which case the default error for the matcher will be used).



36
37
38
# File 'lib/ward/validator.rb', line 36

def message
  @message
end

#scenariosEnumerable<Symbol> (readonly)

The scenarios under which the validator will be run.

Returns:

  • (Enumerable<Symbol>)


22
23
24
# File 'lib/ward/validator.rb', line 22

def scenarios
  @scenarios
end

Instance Method Details

#negative?Boolean

Returns if the validator expects that the matcher not match.

Use with the is_not and does_not DSL keyword.

Returns:

  • (Boolean)


115
116
117
# File 'lib/ward/validator.rb', line 115

def negative?
  @negative
end

#scenario?(scenario) ⇒ Boolean

Returns if the validator should be run as part of the given scenario.

Parameters:

  • scenario (Symbol)

    A name identifying the scenario.

Returns:

  • (Boolean)


105
106
107
# File 'lib/ward/validator.rb', line 105

def scenario?(scenario)
  @scenarios.include?(scenario)
end

#validate(record) ⇒ Array<Boolean, {nil, String, Symbol}>

Determines if the validator is valid for the given record.

The return value deviates from the ValidatorSet API – where #valid? returns only a boolean value – but that’s fine since you shouldn’t be calling Validator#valid? in your applications anyway. :)

Parameters:

  • record (Object)

    The object whose attribute is to be validated.

Returns:

  • (Array<Boolean, {nil, String, Symbol}>)

    Returns an array with two elements. The first is always either true or false, indicating whether the validator passed, and the second is the raw error message returned by the matcher.



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ward/validator.rb', line 77

def validate(record)
  # If the matches? method on the matcher takes two arguments, send in the
  # record as well as the value.
  result = if @matcher.method(:matches?).arity != 1
    @matcher.matches?(@context.value(record), record)
  else
    @matcher.matches?(@context.value(record))
  end

  result, error = if defined?(Rubinius)
    # Rubinius treats any value which responds to #to_a as being
    # array-like, thus multiple assignment breaks if the matcher returns
    # such an object.
    result.is_a?(Array) ? result : [result].flatten
  else
    result
  end

  (!! result) ^ negative? ? [ true, nil ] : [ false, error_for(error) ]
end