Class: FlexArgs::Constraint

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, *constraints, &block) ⇒ Constraint

## Creates a new constraint for the value argument named ‘name`

Constraints can be many, which is indicated by the first element in the ‘constraints` list, or a constraint can be indicated by a custom made block.

The available constraints are:

### ‘Regexp` constraint

These rdoc_specs show the interface that the ‘FlexArgs::Parser` uses to validate constraints, the class is therefore part of the public API and can be used in isolation where it serves.

“‘spec # regexp

new(:for_some_value, %r{x}).("x") => [:ok, "x"]
new(:for_some_value, %r{x}).("y") => [:error, "regexp constraint for_some_value: (?-mix:x) violated by value \"y\""]

“‘

### ‘Range` constraint

“‘spec # range

new(:for_some_int, 1..9).("1") => [:ok, 1]
new(:for_some_int, 1..9).("0") => [:error, "range constraint for_some_int: 1..9 violated by value \"0\""]
new(:for_some_int, 1..9).("y") => [:error, "range constraint for_some_int: 1..9 violated by value \"y\""]

“‘ ### Custom constraint

This is easily implemented by passing a block which will return a pair as described above, but also note two more features of the custom constraint

  • exceptions will be caught and transformed into an error, thusly simplyfing the code block:

  • and values can be transformed

“‘spec # custom

constraint = new :even do
  value = Integer(it)
  value.even? ? [:ok, value / 2] : [:error, "not even"]
end

expect(constraint.("84")).to eq([:ok, 42])
expect(constraint.("21")).to eq([:error, "custom constraint even: violated by value \"21\" with message: \"not even\""])

exception_message = '"invalid value for Integer(): \\"abc\\" (ArgumentError)"'
complete_message = "custom constraint even: violated by value \"abc\" with message: #{exception_message}"
expect(constraint.("abc")).to eq([:error, complete_message])

“‘

Also note that the correct format of the block’s return value is important

“‘spec # enforce correct format of custom constraint’s block

constraint = new(:bad) { 42 }

expect { constraint.(nil) }
 .to raise_error(ArgumentError, "badly formatted custom block for custom constraint bad returned 42, needed [:ok|:error, value_or_message]")

“‘



67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/flex_args/constraint.rb', line 67

def initialize(name, *constraints, &block)
  @name = name
  case constraints
  in [Regexp => constraint]
    _init_regexp(name, constraint)
  in [Range => range]
    _init_range(name, range)
  else
    raise ArgumentError,
      "illegal constraint spec #{constraints.inspect} for value #{name}" unless block
    _init_custom(name, &block)
  end
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



6
7
8
# File 'lib/flex_args/constraint.rb', line 6

def name
  @name
end

Instance Method Details

#call(value) ⇒ Object



81
82
83
# File 'lib/flex_args/constraint.rb', line 81

def call(value)
  @constrainer.(value)
end