smart_types 0.1.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +57 -0
- data/Gemfile.lock +71 -58
- data/LICENSE.txt +1 -1
- data/README.md +363 -34
- data/Rakefile +0 -1
- data/bin/console +2 -2
- data/lib/smart_core/types/errors.rb +12 -0
- data/lib/smart_core/types/primitive/caster.rb +5 -2
- data/lib/smart_core/types/primitive/checker.rb +5 -2
- data/lib/smart_core/types/primitive/factory/definition_context.rb +140 -4
- data/lib/smart_core/types/primitive/factory/runtime_type_builder.rb +53 -0
- data/lib/smart_core/types/primitive/factory.rb +104 -7
- data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
- data/lib/smart_core/types/primitive/invariant_control/chain.rb +61 -0
- data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
- data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
- data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
- data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
- data/lib/smart_core/types/primitive/invariant_control/single.rb +57 -0
- data/lib/smart_core/types/primitive/invariant_control.rb +67 -0
- data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +26 -2
- data/lib/smart_core/types/primitive/mult_factory.rb +59 -10
- data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
- data/lib/smart_core/types/primitive/mult_validator.rb +42 -0
- data/lib/smart_core/types/primitive/nilable_factory.rb +31 -9
- data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
- data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
- data/lib/smart_core/types/primitive/runtime_attributes_checker.rb +77 -0
- data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +25 -1
- data/lib/smart_core/types/primitive/sum_factory.rb +59 -10
- data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
- data/lib/smart_core/types/primitive/sum_validator.rb +117 -0
- data/lib/smart_core/types/primitive/undefined_caster.rb +4 -1
- data/lib/smart_core/types/primitive/validator/result.rb +78 -0
- data/lib/smart_core/types/primitive/validator.rb +93 -0
- data/lib/smart_core/types/primitive.rb +99 -15
- data/lib/smart_core/types/protocol/instance_of.rb +19 -0
- data/lib/smart_core/types/protocol.rb +7 -0
- data/lib/smart_core/types/value/array.rb +3 -0
- data/lib/smart_core/types/value/big_decimal.rb +4 -1
- data/lib/smart_core/types/value/boolean.rb +3 -0
- data/lib/smart_core/types/value/class.rb +3 -0
- data/lib/smart_core/types/value/date.rb +3 -0
- data/lib/smart_core/types/value/date_time.rb +3 -0
- data/lib/smart_core/types/value/enumerable.rb +1 -1
- data/lib/smart_core/types/value/enumerator.rb +13 -0
- data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
- data/lib/smart_core/types/value/float.rb +3 -0
- data/lib/smart_core/types/value/hash.rb +3 -0
- data/lib/smart_core/types/value/integer.rb +3 -0
- data/lib/smart_core/types/value/io.rb +13 -0
- data/lib/smart_core/types/value/method.rb +9 -0
- data/lib/smart_core/types/value/module.rb +3 -0
- data/lib/smart_core/types/value/nil.rb +0 -2
- data/lib/smart_core/types/value/numeric.rb +3 -0
- data/lib/smart_core/types/value/proc.rb +3 -0
- data/lib/smart_core/types/value/range.rb +9 -0
- data/lib/smart_core/types/value/rational.rb +13 -0
- data/lib/smart_core/types/value/set.rb +21 -0
- data/lib/smart_core/types/value/string.rb +3 -0
- data/lib/smart_core/types/value/string_io.rb +15 -0
- data/lib/smart_core/types/value/symbol.rb +3 -0
- data/lib/smart_core/types/value/text.rb +6 -4
- data/lib/smart_core/types/value/time.rb +3 -0
- data/lib/smart_core/types/value/time_based.rb +8 -5
- data/lib/smart_core/types/value/unbound_method.rb +9 -0
- data/lib/smart_core/types/value.rb +9 -0
- data/lib/smart_core/types/variadic/array_of.rb +23 -0
- data/lib/smart_core/types/variadic/enum.rb +11 -0
- data/lib/smart_core/types/variadic/tuple.rb +23 -0
- data/lib/smart_core/types/variadic.rb +10 -0
- data/lib/smart_core/types/version.rb +2 -1
- data/lib/smart_core/types.rb +2 -0
- data/smart_types.gemspec +5 -4
- metadata +61 -18
- data/.travis.yml +0 -21
- data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
- data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
- data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
+
# @version 0.3.0
|
5
6
|
class SmartCore::Types::Primitive::UndefinedCaster < SmartCore::Types::Primitive::Caster
|
6
7
|
# @param expression [NilClass, Any]
|
7
8
|
# @return [void]
|
@@ -13,13 +14,15 @@ class SmartCore::Types::Primitive::UndefinedCaster < SmartCore::Types::Primitive
|
|
13
14
|
end
|
14
15
|
|
15
16
|
# @param value [Any]
|
17
|
+
# @param runtime_attributes [Array<Any>]
|
16
18
|
# @return [void]
|
17
19
|
#
|
18
20
|
# @raise [SmartCore::Types::TypeCastingUnsupportedError]
|
19
21
|
#
|
20
22
|
# @pai private
|
21
23
|
# @since 0.1.0
|
22
|
-
|
24
|
+
# @version 0.3.0
|
25
|
+
def call(value, runtime_attributes)
|
23
26
|
raise(SmartCore::Types::TypeCastingUnsupportedError, <<~ERROR_MESSAGE)
|
24
27
|
'This type has no support for type casting'
|
25
28
|
ERROR_MESSAGE
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.2.0
|
5
|
+
class SmartCore::Types::Primitive::Validator::Result
|
6
|
+
# @return [Array]
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
# @since 0.2.0
|
10
|
+
NO_INVARIANT_ERRORS = [].freeze
|
11
|
+
|
12
|
+
# @return [SmartCore::Types::Primitive]
|
13
|
+
#
|
14
|
+
# @api public
|
15
|
+
# @since 0.2.0
|
16
|
+
attr_reader :type
|
17
|
+
|
18
|
+
# @return [Boolean]
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
# @since 0.2.0
|
22
|
+
attr_reader :is_valid_check
|
23
|
+
alias_method :valid_check?, :is_valid_check
|
24
|
+
|
25
|
+
# @return [Any]
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
# @since 0.2.0
|
29
|
+
attr_reader :checked_value
|
30
|
+
alias_method :value, :checked_value
|
31
|
+
|
32
|
+
# @return [Array<String>]
|
33
|
+
#
|
34
|
+
# @api public
|
35
|
+
# @since 0.2.0
|
36
|
+
attr_reader :invariant_errors
|
37
|
+
alias_method :errors, :invariant_errors
|
38
|
+
alias_method :error_codes, :invariant_errors
|
39
|
+
|
40
|
+
# @param type [SmartCore::Types::Primitive]
|
41
|
+
# @param checked_value [Any]
|
42
|
+
# @param is_valid_check [Boolean]
|
43
|
+
# @param invariant_errors [Array<String>]
|
44
|
+
# @return [void]
|
45
|
+
#
|
46
|
+
# @api private
|
47
|
+
# @since 0.2.0
|
48
|
+
def initialize(type, checked_value, is_valid_check, invariant_errors = NO_INVARIANT_ERRORS.dup)
|
49
|
+
@type = type
|
50
|
+
@checked_value = checked_value
|
51
|
+
@is_valid_check = is_valid_check
|
52
|
+
@invariant_errors = invariant_errors.tap(&:freeze)
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Boolean]
|
56
|
+
#
|
57
|
+
# @api public
|
58
|
+
# @since 0.2.0
|
59
|
+
def valid_invariants?
|
60
|
+
invariant_errors.empty?
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [Boolean]
|
64
|
+
#
|
65
|
+
# @api public
|
66
|
+
# @since 0.2.0
|
67
|
+
def success?
|
68
|
+
valid_check? && invariant_errors.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
#
|
73
|
+
# @api public
|
74
|
+
# @since 0.2.0
|
75
|
+
def failure?
|
76
|
+
!success?
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# @api private
|
4
|
+
# @since 0.2.0
|
5
|
+
# @version 0.3.0
|
6
|
+
class SmartCore::Types::Primitive::Validator
|
7
|
+
require_relative 'validator/result'
|
8
|
+
|
9
|
+
# @return [SmartCore::Type::Primitive]
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.2.0
|
13
|
+
attr_reader :type
|
14
|
+
|
15
|
+
# @return [SmartCore::Types::Primitive::Checker]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
# @since 0.2.0
|
19
|
+
attr_reader :type_checker
|
20
|
+
|
21
|
+
# @return [SmartCore::Types::Primitive::InvariantControl]
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
# @since 0.2.0
|
25
|
+
attr_reader :invariant_control
|
26
|
+
|
27
|
+
# @param type_checker [SmartCore::Types::Primitive::Checker]
|
28
|
+
# @param invariant_control [SmartCore::Types::Primitive::InvariantControl]
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
# @api private
|
32
|
+
# @since 0.2.0
|
33
|
+
def initialize(type_checker, invariant_control)
|
34
|
+
@type = nil
|
35
|
+
@type_checker = type_checker
|
36
|
+
@invariant_control = invariant_control
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param type [SmartCore::Types::Primitive]
|
40
|
+
# @return [SmartCore::Types::Primitive::Validator]
|
41
|
+
#
|
42
|
+
# @api private
|
43
|
+
# @since 0.3.0
|
44
|
+
def ___copy_for___(type)
|
45
|
+
self.class.new(type_checker, invariant_control).tap do |instance_copy|
|
46
|
+
instance_copy.___assign_type___(type)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param type [SmartCore::Types::Primitive]
|
51
|
+
# @return [void]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
# @since 0.2.0
|
55
|
+
def ___assign_type___(type)
|
56
|
+
@type = type
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param value [Any]
|
60
|
+
# @return [Boolean]
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
# @since 0.2.0
|
64
|
+
def valid?(value)
|
65
|
+
validate(value).success?
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param value [Any]
|
69
|
+
# @return [SmartCore::Types::Primitive::Validator::Result]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
# @since 0.2.0
|
73
|
+
# @version 0.3.0
|
74
|
+
def validate(value)
|
75
|
+
checker_result = type_checker.call(value, type.runtime_attributes) # => Boolean
|
76
|
+
return Result.new(type, value, checker_result) unless checker_result
|
77
|
+
invariant_result = invariant_control.check(value, type.runtime_attributes)
|
78
|
+
invariant_errors = invariant_result.invariant_errors.map { |error| "#{type.name}.#{error}" }
|
79
|
+
Result.new(type, value, checker_result, invariant_errors)
|
80
|
+
end
|
81
|
+
|
82
|
+
# @param value [Any]
|
83
|
+
# @return [void]
|
84
|
+
#
|
85
|
+
# @raise [SmartCore::Types::TypeError]
|
86
|
+
#
|
87
|
+
# @api private
|
88
|
+
# @since 0.2.0
|
89
|
+
def validate!(value)
|
90
|
+
return if validate(value).success?
|
91
|
+
raise(SmartCore::Types::TypeError, 'Invalid type')
|
92
|
+
end
|
93
|
+
end
|
@@ -2,21 +2,28 @@
|
|
2
2
|
|
3
3
|
# @api private
|
4
4
|
# @since 0.1.0
|
5
|
+
# @version 0.3.0
|
5
6
|
class SmartCore::Types::Primitive
|
7
|
+
require_relative 'primitive/checker'
|
6
8
|
require_relative 'primitive/caster'
|
9
|
+
require_relative 'primitive/runtime_attributes_checker'
|
7
10
|
require_relative 'primitive/undefined_caster'
|
8
|
-
require_relative 'primitive/
|
9
|
-
require_relative 'primitive/
|
10
|
-
require_relative 'primitive/sum_checker'
|
11
|
-
require_relative 'primitive/mult_checker'
|
11
|
+
require_relative 'primitive/invariant_control'
|
12
|
+
require_relative 'primitive/validator'
|
12
13
|
require_relative 'primitive/factory'
|
14
|
+
require_relative 'primitive/sum_validator'
|
13
15
|
require_relative 'primitive/sum_factory'
|
16
|
+
require_relative 'primitive/mult_validator'
|
14
17
|
require_relative 'primitive/mult_factory'
|
18
|
+
require_relative 'primitive/nilable_validator'
|
15
19
|
require_relative 'primitive/nilable_factory'
|
16
20
|
|
17
21
|
class << self
|
18
22
|
# @param type_name [String, Symbol]
|
19
23
|
# @param type_definition [Block]
|
24
|
+
# @yield [type]
|
25
|
+
# @yieldparam type [SmartCore::Types::Primitive::DefinitionContext]
|
26
|
+
# @yieldreturn [void]
|
20
27
|
# @return [SmartCore::Types::Primitive]
|
21
28
|
#
|
22
29
|
# @api public
|
@@ -26,11 +33,30 @@ class SmartCore::Types::Primitive
|
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
29
|
-
# @
|
36
|
+
# @note NilClass is suitable for sum-types, mult-types and nilable types.
|
37
|
+
# @return [String, NilClass]
|
38
|
+
#
|
39
|
+
# @api public
|
40
|
+
# @since 0.2.0
|
41
|
+
attr_reader :name
|
42
|
+
|
43
|
+
# @return [Class<SmartCore::Types::Primitive>]
|
30
44
|
#
|
31
45
|
# @api private
|
32
|
-
# @since 0.
|
33
|
-
attr_reader :
|
46
|
+
# @since 0.3.0
|
47
|
+
attr_reader :category
|
48
|
+
|
49
|
+
# @return [Array<Any>]
|
50
|
+
#
|
51
|
+
# @api private
|
52
|
+
# @since 0.3.0
|
53
|
+
attr_reader :runtime_attributes
|
54
|
+
|
55
|
+
# @return [SmartCore::Types::Primitive::RuntimeAttributesChecker]
|
56
|
+
#
|
57
|
+
# @api private
|
58
|
+
# @since 0.3.0
|
59
|
+
attr_reader :runtime_attributes_checker
|
34
60
|
|
35
61
|
# @return [SmartCore::Types::Primitive::Caster]
|
36
62
|
#
|
@@ -38,17 +64,53 @@ class SmartCore::Types::Primitive
|
|
38
64
|
# @since 0.1.0
|
39
65
|
attr_reader :caster
|
40
66
|
|
41
|
-
# @
|
67
|
+
# @return [SmartCore::Types::Primitive::Validator]
|
68
|
+
# @return [SmartCore::Types::Primitive::SumValidator]
|
69
|
+
# @return [SmartCore::Types::Primitive::MultValidator]
|
70
|
+
# @return [SmartCore::Types::primitive::NilableValidator]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
# @since 0.2.0
|
74
|
+
attr_reader :validator
|
75
|
+
|
76
|
+
# @param name [String, NilClass] NilClass is suitable for sum-types, mult-types and nilable types.
|
77
|
+
# @param category [Class<SmartCore::Types::Primitive>, NilClass]
|
78
|
+
# @param validator [
|
79
|
+
# SmartCore::Types::Primitive::Validator,
|
80
|
+
# SmartCore::Types::Primitive::SumValidator,
|
81
|
+
# SmartCore::Types::Primitive::MultValidator,
|
82
|
+
# SmartCore::Types::Primitive::NilableValidator
|
83
|
+
# ]
|
42
84
|
# @param caster [SmartCore::Types::Primitive::Caster]
|
85
|
+
# @param runtime_attributes_checker [SmartCore::Types::Primitive::RuntimeAttributesChecker]
|
86
|
+
# @param runtime_attributes [Array<Any>]
|
43
87
|
# @return [void]
|
44
88
|
#
|
45
89
|
# @api private
|
46
90
|
# @since 0.1.0
|
47
|
-
|
48
|
-
|
49
|
-
|
91
|
+
# @version 0.3.0
|
92
|
+
# rubocop:disable Metrics/ParameterLists
|
93
|
+
def initialize(name, category, validator, caster, runtime_attributes_checker, *runtime_attributes)
|
94
|
+
@name = name
|
95
|
+
@category = category
|
96
|
+
@validator = validator
|
50
97
|
@caster = caster
|
51
98
|
@nilable = nil
|
99
|
+
@runtime_attributes_checker = runtime_attributes_checker
|
100
|
+
@runtime_attributes = runtime_attributes
|
101
|
+
@lock = SmartCore::Engine::Lock.new
|
102
|
+
end
|
103
|
+
# rubocop:enable Metrics/ParameterLists
|
104
|
+
|
105
|
+
# @param cloneable_instance [SmartCore::Types::Primitive]
|
106
|
+
# @return [SmartCore::Types::Primitive]
|
107
|
+
#
|
108
|
+
# @api private
|
109
|
+
# @since 0.3.0
|
110
|
+
def initialize_copy(cloneable_instance)
|
111
|
+
lock.synchronize do
|
112
|
+
self.class::Factory::RuntimeTypeBuilder.initialize_clone(self, cloneable_instance)
|
113
|
+
end
|
52
114
|
end
|
53
115
|
|
54
116
|
# @param value [Any]
|
@@ -56,20 +118,38 @@ class SmartCore::Types::Primitive
|
|
56
118
|
#
|
57
119
|
# @api public
|
58
120
|
# @since 0.1.0
|
121
|
+
# @since 0.2.0
|
59
122
|
def valid?(value)
|
60
|
-
|
123
|
+
validator.valid?(value)
|
61
124
|
end
|
62
125
|
|
63
126
|
# @param value [Any]
|
64
127
|
# @return [void]
|
65
128
|
#
|
66
129
|
# @raise [SmartCore::Types::TypeError]
|
130
|
+
# @see SmartCore::Primitive::Validator
|
131
|
+
# @see SmartCore::Primitive::MultValidator
|
132
|
+
# @see SmartCore::Primitive::SumValidator
|
133
|
+
# @see SmartCore::Primitive::NilableValidator
|
67
134
|
#
|
68
135
|
# @api public
|
69
136
|
# @since 0.1.0
|
137
|
+
# @version 0.2.0
|
70
138
|
def validate!(value)
|
71
|
-
|
72
|
-
|
139
|
+
validator.validate!(value)
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [SmartCore::Types::Primitive::Validator::Result]
|
143
|
+
#
|
144
|
+
# @see SmartCore::Primitive::Validator
|
145
|
+
# @see SmartCore::Primitive::MultValidator
|
146
|
+
# @see SmartCore::Primitive::SumValidator
|
147
|
+
# @see SmartCore::Primitive::NilableValidator
|
148
|
+
#
|
149
|
+
# @api public
|
150
|
+
# @since 0.2.0
|
151
|
+
def validate(value)
|
152
|
+
validator.validate(value)
|
73
153
|
end
|
74
154
|
|
75
155
|
# @param value [Any]
|
@@ -77,8 +157,12 @@ class SmartCore::Types::Primitive
|
|
77
157
|
#
|
78
158
|
# @api public
|
79
159
|
# @since 0.1.0
|
160
|
+
# @version 0.3.0
|
80
161
|
def cast(value)
|
81
|
-
|
162
|
+
# TODO (0.x.0):
|
163
|
+
# refactor with ValueTransformer with internal reference to the type object
|
164
|
+
# in Validator manner (in order to avoid explicit #runtime_attributes passing)
|
165
|
+
caster.call(value, runtime_attributes)
|
82
166
|
end
|
83
167
|
|
84
168
|
# @return [SmartCore::Types::Primitive]
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using SmartCore::Ext::BasicObjectAsObject
|
4
|
+
|
5
|
+
# @api public
|
6
|
+
# @since 0.3.0
|
7
|
+
SmartCore::Types::Protocol.define_type(:InstanceOf) do |type|
|
8
|
+
type.runtime_attributes_checker do |runtime_attrs|
|
9
|
+
runtime_attrs.any? && runtime_attrs.all? do |runtime_attr|
|
10
|
+
runtime_attr.is_a?(::Class)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
type.define_checker do |value, expected_types|
|
15
|
+
expected_types.any? && expected_types.any? do |expected_type|
|
16
|
+
value.is_a?(expected_type)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,15 +3,18 @@
|
|
3
3
|
require 'bigdecimal'
|
4
4
|
require 'bigdecimal/util'
|
5
5
|
|
6
|
+
using SmartCore::Ext::BasicObjectAsObject
|
7
|
+
|
6
8
|
# @api public
|
7
9
|
# @since 0.1.0
|
10
|
+
# @version 0.3.0
|
8
11
|
SmartCore::Types::Value.define_type(:BigDecimal) do |type|
|
9
12
|
type.define_checker do |value|
|
10
13
|
value.is_a?(::BigDecimal)
|
11
14
|
end
|
12
15
|
|
13
16
|
type.define_caster do |value|
|
14
|
-
if SmartCore::Types::Value::
|
17
|
+
if SmartCore::Types::Value::Numeric.valid?(value)
|
15
18
|
value = SmartCore::Types::Value::String.cast(value)
|
16
19
|
end
|
17
20
|
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using SmartCore::Ext::BasicObjectAsObject
|
4
|
+
|
3
5
|
# @api public
|
4
6
|
# @since 0.1.0
|
7
|
+
# @version 0.3.0
|
5
8
|
SmartCore::Types::Value.define_type(:Boolean) do |type|
|
6
9
|
type.define_checker do |value|
|
7
10
|
value.is_a?(::TrueClass) || value.is_a?(::FalseClass)
|