y_support 2.1.5 → 2.1.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +675 -0
- data/Rakefile +1 -1
- data/lib/y_support/abstract_algebra.rb +1 -0
- data/lib/y_support/all.rb +1 -0
- data/lib/y_support/core_ext/array.rb +2 -2
- data/lib/y_support/core_ext/class/misc.rb +2 -3
- data/lib/y_support/core_ext/class.rb +2 -2
- data/lib/y_support/core_ext/enumerable/misc.rb +1 -1
- data/lib/y_support/core_ext/enumerable.rb +2 -2
- data/lib/y_support/core_ext/hash/misc.rb +26 -39
- data/lib/y_support/core_ext/hash.rb +2 -2
- data/lib/y_support/core_ext/module/misc.rb +39 -1
- data/lib/y_support/core_ext/module.rb +2 -2
- data/lib/y_support/core_ext/numeric/misc.rb +0 -2
- data/lib/y_support/core_ext/numeric.rb +2 -2
- data/lib/y_support/core_ext/object/inspection.rb +0 -2
- data/lib/y_support/core_ext/object/misc.rb +31 -16
- data/lib/y_support/core_ext/object.rb +3 -3
- data/lib/y_support/core_ext/string/misc.rb +7 -7
- data/lib/y_support/core_ext/string.rb +2 -2
- data/lib/y_support/core_ext/symbol/misc.rb +2 -3
- data/lib/y_support/core_ext/symbol.rb +2 -2
- data/lib/y_support/core_ext.rb +0 -2
- data/lib/y_support/inert_recorder.rb +1 -1
- data/lib/y_support/kde.rb +1 -0
- data/lib/y_support/name_magic/array.rb +27 -7
- data/lib/y_support/name_magic/class_methods.rb +52 -58
- data/lib/y_support/name_magic/hash.rb +18 -4
- data/lib/y_support/name_magic/namespace_methods.rb +241 -174
- data/lib/y_support/name_magic.rb +82 -38
- data/lib/y_support/null_object.rb +8 -7
- data/lib/y_support/respond_to.rb +1 -2
- data/lib/y_support/stdlib_ext/matrix/misc.rb +0 -2
- data/lib/y_support/stdlib_ext/matrix.rb +2 -2
- data/lib/y_support/stdlib_ext.rb +1 -0
- data/lib/y_support/try.rb +1 -1
- data/lib/y_support/typing/array/typing.rb +45 -4
- data/lib/y_support/typing/array.rb +1 -1
- data/lib/y_support/typing/enumerable/typing.rb +26 -28
- data/lib/y_support/typing/enumerable.rb +1 -1
- data/lib/y_support/typing/hash/typing.rb +47 -29
- data/lib/y_support/typing/hash.rb +1 -1
- data/lib/y_support/typing/module/typing.rb +4 -6
- data/lib/y_support/typing/module.rb +1 -1
- data/lib/y_support/typing/object/typing.rb +64 -61
- data/lib/y_support/typing/object.rb +1 -1
- data/lib/y_support/typing.rb +4 -26
- data/lib/y_support/unicode.rb +5 -7
- data/lib/y_support/version.rb +1 -1
- data/lib/y_support/x.rb +11 -8
- data/lib/y_support.rb +2 -2
- data/test/abstract_algebra_test.rb +44 -55
- data/test/inert_recorder_test.rb +13 -18
- data/test/local_object_test.rb +13 -18
- data/test/misc_test.rb +15 -10
- data/test/name_magic_test.rb +1 -1
- data/test/null_object_test.rb +19 -26
- data/test/respond_to_test.rb +15 -16
- data/test/typing_test.rb +100 -103
- data/test/x_test.rb +16 -19
- data/y_support.gemspec +21 -17
- metadata +37 -8
- data/LICENSE +0 -22
@@ -1,8 +1,8 @@
|
|
1
|
-
#encoding: utf-8
|
1
|
+
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'y_support'
|
4
4
|
|
5
|
-
# Null object pattern implementation in YSupport
|
5
|
+
# Null object pattern implementation in +YSupport+. apart from the expected null
|
6
6
|
# object behavior (such as returning self in response to almost all messages),
|
7
7
|
# this null object instances can carry a signature specified by the user upon
|
8
8
|
# creation, which can serve to hint the origin of the null object. (This
|
@@ -17,7 +17,7 @@ class NullObject
|
|
17
17
|
@null_object_signature = null_object_signature
|
18
18
|
end
|
19
19
|
|
20
|
-
# Inquirer whether an object is a NullObject
|
20
|
+
# Inquirer whether an object is a +NullObject+. Again, optional signature
|
21
21
|
# argument can be given to distinguish between different null objects.
|
22
22
|
#
|
23
23
|
def null_object? signature=nil
|
@@ -60,7 +60,7 @@ class NullObject
|
|
60
60
|
#
|
61
61
|
def blank?; true end
|
62
62
|
|
63
|
-
# True if and only if the other object is a NullObject with same signature.
|
63
|
+
# True if and only if the other object is a +NullObject+ with same signature.
|
64
64
|
#
|
65
65
|
def == other
|
66
66
|
other.is_a?( self.class ) &&
|
@@ -78,13 +78,13 @@ end # class nullobject
|
|
78
78
|
|
79
79
|
|
80
80
|
class Object
|
81
|
-
# Always false for ordinary objects, overriden in NullObject instances.
|
81
|
+
# Always false for ordinary objects, overriden in +NullObject+ instances.
|
82
82
|
#
|
83
83
|
def null_object? signature=nil; false end
|
84
84
|
alias :null? :null_object?
|
85
85
|
|
86
|
-
# Converts
|
87
|
-
# specifies the signature of the null object to be created.
|
86
|
+
# Converts +#nil?+-positive objects to a +NullObject+. Second optional
|
87
|
+
# argument specifies the signature of the null object to be created.
|
88
88
|
#
|
89
89
|
def Maybe object, null_object_signature=nil
|
90
90
|
object.nil? ? NullObject.new( null_object_signature ) : object
|
@@ -94,3 +94,4 @@ class Object
|
|
94
94
|
#
|
95
95
|
def Null( signature=nil ); NullObject.new signature end
|
96
96
|
end
|
97
|
+
|
data/lib/y_support/respond_to.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require 'y_support'
|
2
|
-
require '
|
1
|
+
require 'y_support' unless defined? YSupport
|
2
|
+
require File.dirname( __FILE__ ) + '/matrix/misc'
|
data/lib/y_support/stdlib_ext.rb
CHANGED
data/lib/y_support/try.rb
CHANGED
@@ -1,19 +1,17 @@
|
|
1
|
-
#encoding: utf-8
|
2
1
|
class Array
|
3
|
-
#
|
2
|
+
# Runtime assertions for Array.
|
4
3
|
|
5
4
|
# This method takes a block and fails with TypeError, if the receiver array
|
6
5
|
# fails to include the specified element. An optional argument customizes the
|
7
6
|
# error message (element description).
|
8
7
|
#
|
9
|
-
def
|
8
|
+
def aT_include element, what_is_self="array", what_is_element=nil
|
10
9
|
m = "%s is absent from #{what_is_self}!" %
|
11
10
|
if what_is_element then what_is_element.to_s.capitalize else
|
12
11
|
"Element (#{element.class} instance)"
|
13
12
|
end
|
14
13
|
tap { include? element or fail TypeError, m }
|
15
14
|
end
|
16
|
-
alias :aT_include :aT_includes
|
17
15
|
|
18
16
|
# Fails with TypeError if the array contains duplicates (using +#uniq+).
|
19
17
|
#
|
@@ -21,4 +19,47 @@ class Array
|
|
21
19
|
m = "#{what_is_self.to_s.capitalize} non-uniq!"
|
22
20
|
tap { self == uniq or fail TypeError, m }
|
23
21
|
end
|
22
|
+
|
23
|
+
# Fails with TypeError unless the receiver's +#empty?+ returns _true_.
|
24
|
+
#
|
25
|
+
def aT_empty what_is_receiver="array"
|
26
|
+
tap { empty? or fail TypeError, "%s not empty".X!( what_is_receiver ) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Fails with TypeError unless the receiver's +#empty?+ returns _false_.
|
30
|
+
#
|
31
|
+
def aT_not_empty what_is_receiver="array"
|
32
|
+
tap { empty? and fail TypeError, "%s empty".X!( what_is_receiver ) }
|
33
|
+
end
|
34
|
+
|
35
|
+
# This method takes a block and fails with +ArgumentError+ if the receiver
|
36
|
+
# array fails to include the specified element. An optional argument
|
37
|
+
# customizes the error message (element description).
|
38
|
+
#
|
39
|
+
def aA_include element, what_is_self="array", what_is_element=nil
|
40
|
+
m = "%s is absent from #{what_is_self}!" %
|
41
|
+
if what_is_element then what_is_element.to_s.capitalize else
|
42
|
+
"Element (#{element.class} instance)"
|
43
|
+
end
|
44
|
+
tap { include? element or fail ArgumentError, m }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Fails with ArgumentError if the array contains duplicates (using +#uniq+).
|
48
|
+
#
|
49
|
+
def aA_uniq what_is_self="array"
|
50
|
+
m = "#{what_is_self.to_s.capitalize} non-uniq!"
|
51
|
+
tap { self == uniq or fail ArgumentError, m }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Fails with ArgumentError unless the receiver's +#empty?+ returns _true_.
|
55
|
+
#
|
56
|
+
def aA_empty what_is_receiver="array"
|
57
|
+
tap { empty? or fail ArgumentError, "%s not empty".X!( what_is_receiver ) }
|
58
|
+
end
|
59
|
+
|
60
|
+
# Fails with ArgumentError unless the receiver's +#empty?+ returns _false_.
|
61
|
+
#
|
62
|
+
def aA_not_empty what_is_receiver="array"
|
63
|
+
tap { empty? and fail ArgumentError, "%s empty".X!( what_is_receiver ) }
|
64
|
+
end
|
24
65
|
end
|
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require File.dirname( __FILE__ ) + '/array/typing'
|
@@ -1,66 +1,64 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
1
|
module Enumerable
|
4
|
-
# Fails with TypeError unless all the members of the collection comply with
|
5
|
-
# the supplied block criterion. Optional arguments customize the error
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
2
|
+
# Fails with +TypeError+ unless all the members of the collection comply with
|
3
|
+
# the supplied block criterion. Optional arguments customize the error message.
|
4
|
+
# First optional argument describes the collection element, the second one
|
5
|
+
# describes the tested duck type. If the criterion block takes at least one
|
6
|
+
# argument, the receiver elemnts are passed to it (+#all?+ method). If the
|
7
|
+
# criterion block takes no arguments (arity 0), it is gradually executed inside
|
8
|
+
# the elements (using +#instance_exec+). If no block is given, all members are
|
9
|
+
# required to be truey.
|
12
10
|
#
|
13
11
|
def aT_all what_is_collection_element=nil, how_comply=nil, &b
|
14
12
|
e = what_is_collection_element || "collection element"
|
15
13
|
if block_given?
|
16
14
|
m = "Each #{e} must %s!" %
|
17
|
-
( how_comply ? how_comply : "comply with the
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
( how_comply ? how_comply : "comply with the specification" )
|
16
|
+
fail TypeError, m unless ( b.arity == 0 ?
|
17
|
+
all? { |e| e.instance_exec( &b ) } :
|
18
|
+
all? { |e| b.( e ) } )
|
21
19
|
else
|
22
20
|
m = "No #{e} must be nil or false!"
|
23
|
-
|
21
|
+
fail TypeError, m unless all? { |e| e }
|
24
22
|
end
|
25
23
|
return self
|
26
24
|
end
|
27
25
|
|
28
|
-
# Fails with TypeError unless all collection members are
|
26
|
+
# Fails with +TypeError+ unless all collection members are +#kind_of?+ the
|
29
27
|
# class supplied as argument. Second optional argument (collection element
|
30
28
|
# description) customizes the error message.
|
31
29
|
#
|
32
30
|
def aT_all_kind_of klass, what_is_collection_element=nil
|
33
31
|
e = what_is_collection_element || "collection element"
|
34
32
|
m = "Each #{e} must be kind of #{klass}!"
|
35
|
-
|
33
|
+
fail TypeError, m unless all? { |e| e.kind_of? klass }
|
36
34
|
return self
|
37
35
|
end
|
38
36
|
|
39
|
-
# Fails with TypeError unless all collection members declare compliance with
|
40
|
-
#
|
41
|
-
#
|
37
|
+
# Fails with +TypeError+ unless all collection members declare compliance with
|
38
|
+
# the class supplied as an argument. Second optional argument (collection
|
39
|
+
# element description) customizes the error message.
|
42
40
|
#
|
43
41
|
def aT_all_comply klass, what_is_collection_element=nil
|
44
42
|
e = what_is_collection_element || "collection element"
|
45
43
|
m = "Each #{e} must declare compliance to #{klass}!"
|
46
|
-
|
44
|
+
fail TypeError, m unless all? { |e| e.class_complies? klass }
|
47
45
|
return self
|
48
46
|
end
|
49
47
|
|
50
|
-
# Fails with TypeError unless all the collection members declare compliance
|
51
|
-
# with Numeric
|
48
|
+
# Fails with +TypeError+ unless all the collection members declare compliance
|
49
|
+
# with +Numeric+. Second optional argument (collection element description)
|
52
50
|
# customizes the error message.
|
53
51
|
#
|
54
52
|
def aT_all_numeric what_is_collection_element=nil
|
55
53
|
e = what_is_collection_element || "collection element"
|
56
54
|
m = "Each #{e} must declare compliance with Numeric!"
|
57
|
-
|
55
|
+
fail TypeError, m unless all? { |e| e.class_complies? Numeric }
|
58
56
|
return self
|
59
57
|
end
|
60
58
|
|
61
|
-
# Fails with TypeError unless all the collection members are included
|
62
|
-
# collection supplied as argument. Second optional argument (collection
|
63
|
-
#
|
59
|
+
# Fails with +TypeError+ unless all the collection members are included in the
|
60
|
+
# collection supplied as argument. Second optional argument (collection element
|
61
|
+
# description) customizes the error message.
|
64
62
|
#
|
65
63
|
def aT_subset_of other_collection, what_is_receiver_collection=nil,
|
66
64
|
what_is_other_collection=nil
|
@@ -69,7 +67,7 @@ module Enumerable
|
|
69
67
|
oc = what_is_other_collection ? what_is_other_collection.to_s.capitalize :
|
70
68
|
"the specified collection"
|
71
69
|
m = "The #{rc} must be a subset of #{oc}"
|
72
|
-
|
70
|
+
fail TypeError, m unless all? { |e| other_collection.include? e }
|
73
71
|
return self
|
74
72
|
end
|
75
73
|
end
|
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require File.dirname( __FILE__ ) + '/enumerable/typing'
|
@@ -1,12 +1,10 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
1
|
class Hash
|
4
2
|
# Merges the synonymous hash keys into a single key - useful for argument
|
5
3
|
# validation. Returns nil if neither main key, nor synonyms are found.
|
6
4
|
# Returns false (no merging) if the main key was found, but no synonym keys.
|
7
5
|
# Returns true (yes merging) if any of the synonym keys is found and
|
8
6
|
# renamed/merged to the main key. Value collisions in synonym keys (detected
|
9
|
-
# by
|
7
|
+
# by +#==+) raise +ArgumentError+.
|
10
8
|
#
|
11
9
|
def merge_synonym_keys!( key, *synonyms )
|
12
10
|
synonyms.reduce has_key?( key ) ? false : nil do |acc, syn|
|
@@ -20,57 +18,77 @@ class Hash
|
|
20
18
|
delete syn
|
21
19
|
next true
|
22
20
|
else
|
23
|
-
raise
|
21
|
+
raise TypeError, "Value collision between #{key} and its synonym #{syn}!"
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
# supplied as a named argument
|
31
|
-
# will be merged with the main key, modifying the hash.)
|
26
|
+
# Calls +#merge_synonym_keys!+ first, then returns the value under the
|
27
|
+
# specified key. The first argument is the main key, synonym keys may be
|
28
|
+
# supplied as a named argument +:syn!+. (Bang indicates that the synonym
|
29
|
+
# keys will be merged with the main key, thus modifying the hash.)
|
32
30
|
#
|
33
31
|
def may_have key, options={}
|
34
32
|
merge_synonym_keys!( key, *options[:syn!] ).nil?
|
35
33
|
return self[key]
|
36
34
|
end
|
37
35
|
|
38
|
-
# This method behaves
|
39
|
-
#
|
40
|
-
# the key or any synonym has been found.
|
36
|
+
# This method behaves like +#may_have+, but it returns _true_/_false_ value
|
37
|
+
# instead of the value under the specified key.
|
41
38
|
#
|
42
39
|
def has? key, options={}
|
43
|
-
!merge_synonym_keys!( key, *options[:syn!] ).nil?
|
40
|
+
! merge_synonym_keys!( key, *options[:syn!] ).nil?
|
44
41
|
end
|
45
|
-
|
46
|
-
# This
|
42
|
+
|
43
|
+
# This runtime assertion raises +TypeError+ when:
|
47
44
|
# 1. Neither the required key nor any of its synonyms are present.
|
48
45
|
# 2. The supplied criterion block, if any, returns false when applied
|
49
46
|
# to the value of the key in question. If the block takes an argument
|
50
47
|
# (or more arguments), the value is passed in. If the block takes no
|
51
48
|
# arguments (arity 0), it is executed inside the singleton class of the
|
52
|
-
# receiver (using
|
49
|
+
# receiver (using +#instance_exec+ method).
|
53
50
|
#
|
54
51
|
def aT_has key, options={}, &b
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
raise TErr, m unless ( b.arity == 0 ? self[key].instance_exec( &b ) :
|
60
|
-
b.( self[key] ) )
|
52
|
+
fail TypeError, "Key '#{key}' absent!" unless has? key, options
|
53
|
+
self[key].tap do |val|
|
54
|
+
fail TypeError, "Value for #{key} of wrong type!" unless
|
55
|
+
( b.arity == 0 ? val.instance_exec( &b ) : b.( val ) ) if b
|
61
56
|
end
|
62
|
-
return self[key]
|
63
57
|
end
|
64
58
|
alias :must_have :aT_has
|
65
59
|
|
66
|
-
# This method behaves exactly like
|
67
|
-
#
|
60
|
+
# This method behaves exactly like +#aT_has+, but it raises +ArgumentError+
|
61
|
+
# instead of +TypeError+.
|
68
62
|
#
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
63
|
+
def aA_has key, options={}, &b
|
64
|
+
fail ArgumentError, "Key '#{key}' absent!" unless has? key, options
|
65
|
+
self[key].tap do |val|
|
66
|
+
fail ArgumentError, "Value for #{key} of wrong type!" unless
|
67
|
+
( b.arity == 0 ? val.instance_exec( &b ) : b.( val ) ) if b
|
74
68
|
end
|
75
69
|
end
|
70
|
+
|
71
|
+
# Fails with +TypeError+ unless the receiver's +#empty?+ returns _true_.
|
72
|
+
#
|
73
|
+
def aT_empty what_is_receiver="hash"
|
74
|
+
tap { empty? or fail TypeError, "%s not empty".X!( what_is_receiver ) }
|
75
|
+
end
|
76
|
+
|
77
|
+
# Fails with +TypeError+ unless the receiver's `#empty?` returns _false_.
|
78
|
+
#
|
79
|
+
def aT_not_empty what_is_receiver="hash"
|
80
|
+
tap { empty? and fail TypeError, "%s empty".X!( what_is_receiver ) }
|
81
|
+
end
|
82
|
+
|
83
|
+
# Fails with +ArgumentError+ unless the receiver's `#empty?` returns _true_.
|
84
|
+
#
|
85
|
+
def aA_empty what_is_receiver="hash"
|
86
|
+
tap { empty? or fail ArgumentError, "%s not empty".X!( what_is_receiver ) }
|
87
|
+
end
|
88
|
+
|
89
|
+
# Fails with +ArgumentError+ unless the receiver's `#empty?` returns _false_.
|
90
|
+
#
|
91
|
+
def aA_not_empty what_is_receiver="hash"
|
92
|
+
tap { empty? and fail ArgumentError, "%s empty".X!( what_is_receiver ) }
|
93
|
+
end
|
76
94
|
end
|
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require File.dirname( __FILE__ ) + '/hash/typing'
|
@@ -1,16 +1,13 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
1
|
class Module
|
4
2
|
# === Support for typing by declaration
|
5
3
|
|
6
4
|
# Compliance inquirer (declared compliance + ancestors).
|
7
5
|
#
|
8
6
|
def complies?( other_module )
|
9
|
-
other_module.aT_kind_of Module, "other module"
|
10
|
-
compliance.include? other_module
|
7
|
+
compliance.include? other_module.aT_kind_of( Module, "other module" )
|
11
8
|
end
|
12
9
|
|
13
|
-
# Declared
|
10
|
+
# Declared compliance inquirer.
|
14
11
|
#
|
15
12
|
def declares_compliance?( other_module )
|
16
13
|
other_module.aT_kind_of Module, "other module"
|
@@ -31,7 +28,8 @@ class Module
|
|
31
28
|
}.reduce( [], :+ ) ).uniq
|
32
29
|
end
|
33
30
|
|
34
|
-
#
|
31
|
+
# Using this method, the receiver explicitly declares that its interface
|
32
|
+
# complies with another module (class).
|
35
33
|
#
|
36
34
|
def declare_compliance! other_module
|
37
35
|
other_module.aT_kind_of Module, "other module"
|
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require File.dirname( __FILE__ ) + '/module/typing'
|
@@ -1,21 +1,19 @@
|
|
1
|
-
#encoding: utf-8
|
2
|
-
|
3
1
|
require 'active_support/core_ext/object/blank'
|
4
|
-
require '
|
5
|
-
require '
|
2
|
+
require File.dirname( __FILE__ ) + '/../../core_ext/object/inspection'
|
3
|
+
require File.dirname( __FILE__ ) + '/../../core_ext/string/misc'
|
6
4
|
|
7
5
|
class Object
|
8
|
-
# ===
|
6
|
+
# === Typing by declaration
|
9
7
|
|
10
8
|
# Class compliance inquirer (declared compliance + class ancestors).
|
11
9
|
#
|
12
|
-
def class_complies?
|
10
|
+
def class_complies? klass
|
13
11
|
singleton_class_or_class.complies? klass
|
14
12
|
end
|
15
13
|
|
16
14
|
# Declared class compliance.
|
17
15
|
#
|
18
|
-
def class_declares_compliance?
|
16
|
+
def class_declares_compliance? klass
|
19
17
|
singleton_class_or_class.declares_compliance? klass
|
20
18
|
end
|
21
19
|
|
@@ -33,31 +31,29 @@ class Object
|
|
33
31
|
|
34
32
|
# Declaration of class compliance.
|
35
33
|
#
|
36
|
-
def declare_class_compliance!
|
34
|
+
def declare_class_compliance! klass
|
37
35
|
singleton_class_or_class.declare_compliance! klass
|
38
36
|
end
|
39
37
|
|
40
|
-
# ===
|
38
|
+
# === Runtime assertions
|
41
39
|
|
42
|
-
# This method takes a block and fails with TypeError
|
40
|
+
# This method takes a block and fails with +TypeError+, unless the receiver
|
43
41
|
# fullfills the block criterion. Optional arguments customize customize
|
44
42
|
# the error message. First optional argument describes the receiver, the
|
45
43
|
# second one describes the tested duck type. If the criterion block takes
|
46
44
|
# at least one argument, the receiver is passed to it. If the criterion block
|
47
45
|
# takes no arguments (arity 0), it is executed inside the singleton class of
|
48
|
-
# the receiver (using
|
46
|
+
# the receiver (using +#instance_exec+ method). If no block is given, it is
|
49
47
|
# checked, whether the object is truey.
|
50
48
|
#
|
51
49
|
def aT what_is_receiver=insp, how_comply=nil, &b
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# This method takes a block and fails with TypeError, unless the receiver
|
50
|
+
return tap { fail TypeError unless self } unless b
|
51
|
+
return self if b.( self )
|
52
|
+
m = "%s fails " + ( how_comply ? "to #{how_comply}" : "its check" )
|
53
|
+
fail TypeError, m.X!( what_is_receiver )
|
54
|
+
end
|
55
|
+
|
56
|
+
# This method takes a block and fails with +TypeError+, unless the receiver
|
61
57
|
# causes the supplied block <em>to return falsey value</em>. Optional arguments
|
62
58
|
# customize customize the error message. First optional argument describes the
|
63
59
|
# receiver, the second one describes the tested duck type. If the criterion
|
@@ -67,84 +63,91 @@ class Object
|
|
67
63
|
# no block is given, it is checked, whether the object is falsey.
|
68
64
|
#
|
69
65
|
def aT_not what_is_receiver=insp, how_comply=nil, &b
|
70
|
-
tap
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
fail TypeError, m.X!( what_is_receiver )
|
75
|
-
end
|
76
|
-
else fail TypeError if self end
|
77
|
-
end
|
66
|
+
return tap { fail TypeError if self } unless b
|
67
|
+
return self unless b.( self )
|
68
|
+
m = how_comply ? "%s must not #{how_comply}" : "%s fails its check"
|
69
|
+
fail TypeError, m.X!( what_is_receiver )
|
78
70
|
end
|
79
71
|
|
80
|
-
# Fails with TypeError unless the receiver is of the prescribed class. Second
|
72
|
+
# Fails with +TypeError+ unless the receiver is of the prescribed class. Second
|
81
73
|
# optional argument customizes the error message (receiver description).
|
82
74
|
#
|
83
75
|
def aT_kind_of klass, what_is_receiver=insp
|
84
|
-
|
85
|
-
|
86
|
-
end
|
76
|
+
return self if is_a? klass
|
77
|
+
fail TypeError, "%s not a #{klass}".X!( what_is_receiver )
|
87
78
|
end
|
88
79
|
alias aT_is_a aT_kind_of
|
89
80
|
|
90
|
-
# Fails with TypeError unless the receiver declares compliance with the
|
81
|
+
# Fails with +TypeError+ unless the receiver declares compliance with the
|
91
82
|
# given class, or is a descendant of that class. Second optional argument
|
92
83
|
# customizes the error message (receiver description).
|
93
84
|
#
|
94
|
-
def
|
95
|
-
if class_complies? klass
|
96
|
-
|
97
|
-
else self end
|
85
|
+
def aT_complies klass, what_is_receiver=insp
|
86
|
+
return self if class_complies? klass
|
87
|
+
fail TypeError, "%s does not comply with #{klass}".X!( what_is_receiver )
|
98
88
|
end
|
99
|
-
|
100
|
-
|
101
|
-
#
|
102
|
-
# description).
|
89
|
+
alias aT_class_complies aT_complies
|
90
|
+
|
91
|
+
# Fails with +TypeError+ unless the receiver responds to the given method.
|
92
|
+
# Second optional argument customizes the error message (receiver description).
|
103
93
|
#
|
104
94
|
def aT_respond_to method_name, what_is_receiver=insp
|
105
|
-
if respond_to? method_name
|
106
|
-
|
107
|
-
|
108
|
-
end
|
95
|
+
return self if respond_to? method_name
|
96
|
+
fail TypeError,
|
97
|
+
"%s does not respond to '#{method_name}'".X!( what_is_receiver )
|
109
98
|
end
|
110
99
|
alias aT_responds_to aT_respond_to
|
111
|
-
|
112
|
-
# Fails with TypeError unless the receiver, according to
|
100
|
+
|
101
|
+
# Fails with +TypeError+ unless the receiver, according to +#==+ method, is
|
113
102
|
# equal to the argument. Two more optional arguments customize the error
|
114
103
|
# message (receiver description and the description of the other object).
|
115
104
|
#
|
116
105
|
def aT_equal other, what_is_receiver=insp, what_is_other=nil
|
117
|
-
if self == other
|
118
|
-
|
119
|
-
|
120
|
-
end
|
106
|
+
return self if self == other
|
107
|
+
wo = what_is_other || "the prescribed value (#{other.insp})"
|
108
|
+
fail TypeError, "%s must be equal to %s".X!( [ what_is_receiver, wo ] )
|
121
109
|
end
|
122
110
|
|
123
|
-
# Fails with TypeError unless the receiver, according to
|
124
|
-
# from to the argument. Two more optional arguments customize the error
|
111
|
+
# Fails with +TypeError+ unless the receiver, according to +#==+ method,
|
112
|
+
# differs from to the argument. Two more optional arguments customize the error
|
125
113
|
# message (receiver description and the description of the other object).
|
126
114
|
#
|
127
115
|
def aT_not_equal other, what_is_receiver=insp, what_is_other=nil
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
else self end
|
116
|
+
return self unless self == other
|
117
|
+
wo = what_is_other || "the prescribed value (#{other.insp})"
|
118
|
+
fail TypeError, "%s must not == %s".X!( [ what_is_receiver, wo ] )
|
132
119
|
end
|
133
120
|
|
134
|
-
# Fails with TypeError unless
|
135
|
-
#
|
121
|
+
# Fails with +TypeError+ unless activesupport's +#blank+ returns true for
|
122
|
+
# the receiver.
|
136
123
|
#
|
137
124
|
def aT_blank what_is_receiver=insp
|
138
125
|
tap { blank? or fail TypeError, "%s not blank".X!( what_is_receiver ) }
|
139
126
|
end
|
140
127
|
|
141
|
-
# Fails with TypeError unless
|
142
|
-
#
|
128
|
+
# Fails with +TypeError+ unless activesupport's +#present+ returns true for
|
129
|
+
# the receiver.
|
143
130
|
#
|
144
131
|
def aT_present what_is_receiver=insp
|
145
132
|
tap { present? or fail TypeError, "%s not present".X!( what_is_receiver ) }
|
146
133
|
end
|
147
134
|
|
135
|
+
# Fails with +ArgumentError+ unless the +ActiveSupport+ method +#blank+ returns
|
136
|
+
# true for the receiver.
|
137
|
+
#
|
138
|
+
def aA_blank what_is_receiver=insp
|
139
|
+
tap { blank? or fail ArgumentError, "%s not blank".X!( what_is_receiver ) }
|
140
|
+
end
|
141
|
+
|
142
|
+
# Fails with +ArgumentError+ unless the +ActiveSupport+ method #present returns
|
143
|
+
# true for the receiver.
|
144
|
+
#
|
145
|
+
def aA_present what_is_receiver=insp
|
146
|
+
tap {
|
147
|
+
present? or fail ArgumentError, "%s not present".X!( what_is_receiver )
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
148
151
|
private
|
149
152
|
|
150
153
|
# Some objects do not have accessible singleton class. This method returns
|
@@ -1 +1 @@
|
|
1
|
-
require '
|
1
|
+
require File.dirname( __FILE__ ) + '/object/typing'
|