Class: Valligator

Inherits:
Object
  • Object
show all
Defined in:
lib/version.rb,
lib/valligator.rb,
lib/valligator_helper.rb

Defined Under Namespace

Modules: Helper

Constant Summary collapse

VERSION =
'1.0'
Error =
Class.new(StandardError)
ValidationError =
Class.new(Error)
INFINITY =
1/0.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*testees, names: nil) ⇒ Valligator

Creates a new Valligator instance

Examples:

# validate that testee is an instance of String
Valligator.new('foo').is_instance_of(String) #=> OK
# validate that all testees respond to :to_s and :upcase methods
Valligator.new('foo', 'bar', :baz).speaks(:to_s, :upcase) #=> OK
# validate that all testees have size == 3 and start with 'b' and they are Strings
testees = ['boo', 'bar', :baz]
Valligator.new(*testees).has(:size){self == 3}.has(:[], 0){self == 'b'}.is_instance_of(String)
  #=> Valligator::ValidationError: at `testee#3.has.has.is_instance_of'
# validate that all hash values are Integers <= 2
h = { foo: 1, bar: 2, baz: 3 }
Valligator.new(*h.values, names: h.keys).is_instance_of(Integer).asserts(:<= , 2)
  #=> Valligator::ValidationError: at `baz.is_instance_of.asserts'

Parameters:

  • testees (Array<Object>)

    One or more objects to be tested

  • option (Array<String>)

    :names Testee names



40
41
42
43
44
# File 'lib/valligator.rb', line 40

def initialize(*testees, names: nil)
  @testees = testees
  @names   = Array(names)
  @stack   = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/valligator.rb', line 48

def method_missing(method, *args, &block)
  case
  when method[/^does_not_speak_(.+)?$/] then does_not_speak(*args.unshift($1.to_sym))
  when method[/^speaks_(.+)?$/ ]        then speaks(*args.unshift($1.to_sym))
  when method[/^asserts_not_(.+)?$/]    then asserts_not($1.to_sym, *args, &block)
  when method[/^asserts_(.+)?$/]        then asserts($1.to_sym, *args, &block)
  when method[/^does_not_have_(.+)?$/]  then does_not_have($1.to_sym, *args, &block)
  when method[/^has_(.+)?$/]            then has($1.to_sym, *args, &block)
  when method[/^is_not_(.+)?$/]         then is_not($1.to_sym, *args, &block)
  when method[/^is_(.+)?$/]             then is($1.to_sym, *args, &block)
  else super(method, *args, &block)
  end
end

Instance Attribute Details

#namesObject (readonly)

Returns the value of attribute names.



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

def names
  @names
end

#stackObject (readonly)

Returns the value of attribute stack.



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

def stack
  @stack
end

#testeesObject (readonly)

Returns the value of attribute testees.



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

def testees
  @testees
end

Instance Method Details

#asserts(method, *args) {|Object| ... } ⇒ Object

When no block given it passes if the testee, called with a given method and arguments, returns truthy value.

When block is given then it calls the testee with the given method and arguments. Then it calls the block in the context of the value returned above, and if the block returns truthy value the validation passes.

P.S. Truthy value is anything but nil or false.

Examples:

Valligator.new('foo').asserts(:size)                #=> OK
Valligator.new('foo').asserts(:[], 0)               #=> OK
Valligator.new('foo').asserts(:[], 0) {self == 'f'} #=> OK
Valligator.new('foo').asserts(:empty?)              #=> Valligator::ValidationError
Valligator.new('foo').asserts(:[], 100)             #=> Valligator::ValidationError
Valligator.new('foo').asserts(:[], 0) {self == 'F'} #=> Valligator::ValidationError

Parameters:

  • method (Symbol)
  • args (Array<Object>)

Yields:

  • (Object)

Raises:

See Also:



165
166
167
# File 'lib/valligator.rb', line 165

def asserts(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#asserts_not(method, *args) {|Object| ... } ⇒ Object

When no block given it passes if the testee, called with a given method and arguments, returns falsy value.

When block is given then it calls the testee with the given method and arguments. Then it calls the block in the context of the value returned above, and if the block returns falsy value the validation passes.

P.S. Falsy value is either nil or false.

Examples:

Valligator.new('foo').asserts_not(:size)                #=> Valligator::ValidationError
Valligator.new('foo').asserts_not(:[], 0)               #=> Valligator::ValidationError
Valligator.new('foo').asserts_not(:[], 0) {self == 'f'} #=> Valligator::ValidationError
Valligator.new('foo').asserts_not(:empty?)              #=> OK
Valligator.new('foo').asserts_not(:[], 100)             #=> OK
Valligator.new('foo').asserts_not(:[], 0) {self == 'F'} #=> OK

Parameters:

  • method (Symbol)
  • args (Array<Object>)

Yields:

  • (Object)

Raises:

See Also:



194
195
196
# File 'lib/valligator.rb', line 194

def asserts_not(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#does_not_have(method, *args, &block) ⇒ Object

Is an alias for #asserts_not method



222
223
224
# File 'lib/valligator.rb', line 222

def does_not_have(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#does_not_speak(*methods) ⇒ Valligator

Passes when the testee does not respond to all the methods

Examples:

Valligator.new('foo').does_not_speak(:foo, :boo)  #=> OK
Valligator.new('foo').does_not_speak(:foo, :size) #=> Valligator::ValidationError

Parameters:

  • methods (Array<Symbols>)

Returns:

Raises:



136
137
138
# File 'lib/valligator.rb', line 136

def does_not_speak(*methods)
  clone._speaks(__method__, *methods)
end

#has(method, *args, &block) ⇒ Object

Is an alias for #asserts method



215
216
217
# File 'lib/valligator.rb', line 215

def has(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#is(method, *args, &block) ⇒ Object

Is an alias for #asserts method



201
202
203
# File 'lib/valligator.rb', line 201

def is(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#is_a(*classes) ⇒ Object

Is an alias for #is_instance_of method



99
100
101
# File 'lib/valligator.rb', line 99

def is_a(*classes)
  clone._is_instance_of(__method__, *classes)
end

#is_instance_of(*classes) ⇒ Valligator

Passes when the testee is an instance of either of the classes

Examples:

Valligator.new('foo').is_instance_of(Integer, String) #=> OK
Valligator.new('foo').is_instance_of(Integer, Array)  #=> Valligator::ValidationError

Parameters:

  • classes (Array<Class>)

Returns:

Raises:

See Also:



75
76
77
# File 'lib/valligator.rb', line 75

def is_instance_of(*classes)
  clone._is_instance_of(__method__, *classes)
end

#is_not(method, *args, &block) ⇒ Object

Is an alias for #asserts_not method



208
209
210
# File 'lib/valligator.rb', line 208

def is_not(method, *args, &block)
  clone._asserts(__method__, method, *args, &block)
end

#is_not_a(*classes) ⇒ Object

Is an alias for #is_not_instance_of method



106
107
108
# File 'lib/valligator.rb', line 106

def is_not_a(*classes)
  clone._is_instance_of(__method__, *classes)
end

#is_not_instance_of(*classes) ⇒ Valligator

Passes when the testee is not an instance of all of the classes

Examples:

Valligator.new('foo').is_not_instance_of(Integer, String) #=> Valligator::ValidationError
Valligator.new('foo').is_not_instance_of(Integer, Array) #=> OK

Parameters:

  • classes (Array<Class>)

Returns:

Raises:

See Also:



92
93
94
# File 'lib/valligator.rb', line 92

def is_not_instance_of(*classes)
  clone._is_instance_of(__method__, *classes)
end

#speaks(*methods) ⇒ Valligator

Passes when the testee responds to all the methods

Examples:

Valligator.new('foo').speaks(:size, :empty?) #=> OK
Valligator.new('foo').speaks(:size, :foo)    #=> Valligator::ValidationError

Parameters:

  • methods (Array<Symbols>)

Returns:

Raises:



121
122
123
# File 'lib/valligator.rb', line 121

def speaks(*methods)
  clone._speaks(__method__, *methods)
end