Class: ConditionChecker

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

Overview

The ConditionChecker supplied the DSL host environment to evaluate expressions in the Preconditions DSL language. The #is method takes a block that is evaluated in the context of the ConditionChecker instance, with access to all of the ConditionChecker methods. Typical usage will be of the form:

Preconditions.check(x).is { not_nil and responds_to(:hello)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(arg, name = nil, &block) ⇒ ConditionChecker

Returns a new instance of ConditionChecker.



11
12
13
14
# File 'lib/condition_checker.rb', line 11

def initialize(arg, name=nil, &block)
  @arg = arg
  @name = name
end

Instance Attribute Details

#argObject (readonly)

Returns the value of attribute arg.



9
10
11
# File 'lib/condition_checker.rb', line 9

def arg
  @arg
end

#nameObject (readonly)

Returns the value of attribute name.



9
10
11
# File 'lib/condition_checker.rb', line 9

def name
  @name
end

Instance Method Details

#can_respond_to(method_symbol) ⇒ Object

DSL call. Establishes that the checked argument can respond to the requested method, identified by symbol.

Returns:

  • true



54
55
56
57
58
59
# File 'lib/condition_checker.rb', line 54

def can_respond_to(method_symbol)
  if !arg.respond_to?(method_symbol)
    raise NameError, format_message("must respond to method #{method_symbol}")
  end
  true
end

#has_type(type) ⇒ Object

DSL call. Establishes that the checked argument is of the given type. nil is treated as a bottom type (i.e. it is compatible with all types)

Returns:

  • true



44
45
46
47
48
49
# File 'lib/condition_checker.rb', line 44

def has_type(type)
  if !arg.nil? && !arg.kind_of?(type)
    raise TypeError, format_message("must be of type #{type.name}, but is of type #{arg.class.name}")
  end
  true
end

#is_not_nilObject

DSL call. Establishes that the checked argument is non-nil.

Returns:

  • true



33
34
35
36
37
38
# File 'lib/condition_checker.rb', line 33

def is_not_nil
  if arg.nil?
    raise ArgumentError, format_message("may not be nil")
  end
  true
end

#matches(regex) ⇒ Object

DSL call. Establishes that the checked argument matches the given regular expression

Returns:

  • true



64
65
66
67
68
69
# File 'lib/condition_checker.rb', line 64

def matches(regex)
  if arg !~ regex
    raise ArgumentError, format_message("must match the regex /#{regex.to_s}/")
  end
  true
end

#named(name, &block) ⇒ Object

Set the name of the argument being checked

Parameters:

  • name (String)

    the name of the parameter being checked

Returns:

  • argument if a block is given to evaluate, or self if not to allow for further method chaining



20
21
22
23
24
25
26
27
28
# File 'lib/condition_checker.rb', line 20

def named(name, &block)
  @name = name
  if block_given?
    instance_eval(&block)
    arg
  else
    self
  end
end

#satisfies(msg = nil, &block) ⇒ Object

DSL call. Establishes that the checked argument satisfies an arbitrary condition specified in a block. If the block evaluates to true the argument passes; if it evaluates to false it fails and an [ArgumentError] is raised. An optional message may be supplied to describe what the block is checking.

If the block requests a bound variable that variable will be assigned the value of the argument we’re checking. The block may also access the argument value using the ‘arg` name. Note, also, that the block is a closure and will have natural access to variables in lexical scope at the time the DSL expression is created. Thus, one can do something like:

def sqrt(num)
   Preconditions.check(num) { satisfies { num >= 0 } }
end


82
83
84
85
86
87
88
89
90
91
92
# File 'lib/condition_checker.rb', line 82

def satisfies(msg = nil, &block)
  success = if block.arity > 0
              yield(arg)
            else
              instance_eval(&block)
            end
  if !success
    raise ArgumentError, msg.nil? ? format_message("must satisfy given conditions") : format_message("must be #{msg}")
  end
  true
end