Class: Valligator

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

Defined Under Namespace

Modules: Helper

Constant Summary collapse

VERSION =
File.read(Pathname(__FILE__).dirname.join('../VERSION')).strip
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_kind_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_kind_of(String)
  #=> Valligator::ValidationError: at `testee#3.has.has.is_kind_of'
# validate that all hash values are Integers <= 2
h = { foo: 1, bar: 2, baz: 3 }
Valligator.new(*h.values, names: h.keys).is_kind_of(Integer).asserts(:<= , 2)
  #=> Valligator::ValidationError: at `baz.is_kind_of.asserts'


43
44
45
46
47
# File 'lib/valligator.rb', line 43

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



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/valligator.rb', line 51

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.



13
14
15
# File 'lib/valligator.rb', line 13

def names
  @names
end

#stackObject (readonly)

Returns the value of attribute stack.



14
15
16
# File 'lib/valligator.rb', line 14

def stack
  @stack
end

#testeesObject (readonly)

Returns the value of attribute testees.



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

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

Yields:

  • (Object)

Raises:

See Also:



168
169
170
# File 'lib/valligator.rb', line 168

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

Yields:

  • (Object)

Raises:

See Also:



197
198
199
# File 'lib/valligator.rb', line 197

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



225
226
227
# File 'lib/valligator.rb', line 225

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

Raises:



139
140
141
# File 'lib/valligator.rb', line 139

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

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

Is an alias for #asserts method



218
219
220
# File 'lib/valligator.rb', line 218

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

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

Is an alias for #asserts method



204
205
206
# File 'lib/valligator.rb', line 204

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

#is_a(*classes) ⇒ Object

Is an alias for #is_kind_of method



102
103
104
# File 'lib/valligator.rb', line 102

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

#is_kind_of(*classes) ⇒ Valligator

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

Examples:

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

Raises:

See Also:



78
79
80
# File 'lib/valligator.rb', line 78

def is_kind_of(*classes)
  clone._is_kind_of(__method__, *classes)
end

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

Is an alias for #asserts_not method



211
212
213
# File 'lib/valligator.rb', line 211

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

#is_not_a(*classes) ⇒ Object

Is an alias for #is_not_kind_of method



109
110
111
# File 'lib/valligator.rb', line 109

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

#is_not_kind_of(*classes) ⇒ Valligator

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

Examples:

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

Raises:

See Also:



95
96
97
# File 'lib/valligator.rb', line 95

def is_not_kind_of(*classes)
  clone._is_kind_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

Raises:



124
125
126
# File 'lib/valligator.rb', line 124

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