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