kind 4.0.0 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.tool-versions +1 -1
- data/.travis.sh +39 -7
- data/.travis.yml +1 -2
- data/CHANGELOG.md +486 -28
- data/Gemfile +13 -6
- data/README.md +153 -49
- data/kind.gemspec +1 -1
- data/lib/kind.rb +2 -84
- data/lib/kind/__lib__/action_steps.rb +57 -0
- data/lib/kind/__lib__/attributes.rb +66 -0
- data/lib/kind/__lib__/kind.rb +51 -0
- data/lib/kind/__lib__/of.rb +17 -0
- data/lib/kind/__lib__/strict.rb +49 -0
- data/lib/kind/__lib__/undefined.rb +14 -0
- data/lib/kind/action.rb +127 -0
- data/lib/kind/active_model/validation.rb +3 -4
- data/lib/kind/basic.rb +79 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
- data/lib/kind/dig.rb +21 -5
- data/lib/kind/either.rb +30 -0
- data/lib/kind/either/left.rb +29 -0
- data/lib/kind/either/methods.rb +17 -0
- data/lib/kind/either/monad.rb +65 -0
- data/lib/kind/either/monad/wrapper.rb +19 -0
- data/lib/kind/either/right.rb +38 -0
- data/lib/kind/empty.rb +2 -2
- data/lib/kind/empty/constant.rb +7 -0
- data/lib/kind/enum.rb +63 -0
- data/lib/kind/enum/item.rb +40 -0
- data/lib/kind/enum/methods.rb +72 -0
- data/lib/kind/function.rb +45 -0
- data/lib/kind/functional.rb +89 -0
- data/lib/kind/functional/action.rb +90 -0
- data/lib/kind/immutable_attributes.rb +34 -0
- data/lib/kind/immutable_attributes/initializer.rb +70 -0
- data/lib/kind/immutable_attributes/reader.rb +38 -0
- data/lib/kind/maybe.rb +37 -12
- data/lib/kind/maybe/methods.rb +21 -0
- data/lib/kind/maybe/monad.rb +82 -0
- data/lib/kind/maybe/monad/wrapper.rb +19 -0
- data/lib/kind/maybe/none.rb +12 -19
- data/lib/kind/maybe/some.rb +68 -26
- data/lib/kind/maybe/typed.rb +11 -5
- data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +9 -7
- data/lib/kind/monad.rb +22 -0
- data/lib/kind/monads.rb +5 -0
- data/lib/kind/objects.rb +17 -0
- data/lib/kind/objects/basic_object.rb +43 -0
- data/lib/kind/objects/modules.rb +32 -0
- data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
- data/lib/kind/objects/nil.rb +17 -0
- data/lib/kind/objects/not_nil.rb +9 -0
- data/lib/kind/objects/object.rb +56 -0
- data/lib/kind/objects/respond_to.rb +30 -0
- data/lib/kind/objects/union_type.rb +44 -0
- data/lib/kind/presence.rb +4 -2
- data/lib/kind/result.rb +31 -0
- data/lib/kind/result/abstract.rb +53 -0
- data/lib/kind/result/failure.rb +33 -0
- data/lib/kind/result/methods.rb +17 -0
- data/lib/kind/result/monad.rb +74 -0
- data/lib/kind/result/monad/wrapper.rb +19 -0
- data/lib/kind/result/success.rb +53 -0
- data/lib/kind/strict/disabled.rb +34 -0
- data/lib/kind/try.rb +21 -11
- data/lib/kind/validator.rb +111 -0
- data/lib/kind/version.rb +1 -1
- metadata +78 -48
- data/lib/kind/active_model/kind_validator.rb +0 -96
- data/lib/kind/core.rb +0 -9
- data/lib/kind/core/deprecation.rb +0 -29
- data/lib/kind/core/kind.rb +0 -61
- data/lib/kind/core/undefined.rb +0 -7
- data/lib/kind/deprecations/built_in_type_checkers.rb +0 -23
- data/lib/kind/deprecations/checker.rb +0 -16
- data/lib/kind/deprecations/checker/factory.rb +0 -31
- data/lib/kind/deprecations/checker/protocol.rb +0 -73
- data/lib/kind/deprecations/is.rb +0 -35
- data/lib/kind/deprecations/of.rb +0 -258
- data/lib/kind/deprecations/types.rb +0 -121
- data/lib/kind/error.rb +0 -15
- data/lib/kind/maybe/result.rb +0 -51
- data/lib/kind/type_checker.rb +0 -73
- data/lib/kind/type_checkers.rb +0 -30
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
warn '[DEPRECATION] "kind/active_model/validation" is deprecated; use "kind/validator" instead. ' \
|
4
|
+
'It will be removed on next major release.'
|
5
|
+
|
4
6
|
require 'kind/validator'
|
5
|
-
require 'active_model'
|
6
|
-
require 'active_model/validations'
|
7
|
-
require_relative 'kind_validator'
|
data/lib/kind/basic.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/version'
|
4
|
+
|
5
|
+
require 'kind/__lib__/kind'
|
6
|
+
require 'kind/__lib__/undefined'
|
7
|
+
|
8
|
+
require 'kind/basic/undefined'
|
9
|
+
require 'kind/basic/error'
|
10
|
+
|
11
|
+
module Kind
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def is?(kind, arg)
|
15
|
+
KIND.is?(kind, arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
def is(*args)
|
19
|
+
warn '[DEPRECATION] Kind.is will behave like Kind.is! in the next major release; ' \
|
20
|
+
'use Kind.is? instead.'
|
21
|
+
|
22
|
+
is?(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
def is!(kind, arg, label: nil)
|
26
|
+
return arg if KIND.is?(kind, arg)
|
27
|
+
|
28
|
+
label_text = label ? "#{label}: " : ''
|
29
|
+
|
30
|
+
raise Kind::Error.new("#{label_text}#{arg} expected to be a #{kind}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def of?(kind, *args)
|
34
|
+
KIND.of?(kind, args)
|
35
|
+
end
|
36
|
+
|
37
|
+
def of_class?(value)
|
38
|
+
OF.class?(value)
|
39
|
+
end
|
40
|
+
|
41
|
+
def of_module?(value)
|
42
|
+
OF.module?(value)
|
43
|
+
end
|
44
|
+
|
45
|
+
def respond_to?(value, *method_names)
|
46
|
+
return super(value) if method_names.empty?
|
47
|
+
|
48
|
+
KIND.interface?(method_names, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def of(kind, value, label: nil)
|
52
|
+
STRICT.object_is_a(kind, value, label)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :of!, :of
|
56
|
+
|
57
|
+
def of_class(value)
|
58
|
+
STRICT.class!(value)
|
59
|
+
end
|
60
|
+
|
61
|
+
def of_module(value)
|
62
|
+
STRICT.module!(value)
|
63
|
+
end
|
64
|
+
|
65
|
+
def of_module_or_class(value)
|
66
|
+
STRICT.module_or_class(value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def respond_to(value, *method_names)
|
70
|
+
method_names.each { |method_name| KIND.respond_to!(method_name, value) }
|
71
|
+
|
72
|
+
value
|
73
|
+
end
|
74
|
+
alias_method :respond_to!, :respond_to
|
75
|
+
|
76
|
+
def value(kind, value, default:)
|
77
|
+
KIND.value(kind, value, of(kind, default))
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Error < StandardError
|
5
|
+
INVALID_DEFAULT_ARG = 'the default value must be defined as an argument or block'.freeze
|
6
|
+
|
7
|
+
def self.wrong_number_of_args!(given:, expected:)
|
8
|
+
raise ArgumentError, "wrong number of arguments (given #{given}, expected #{expected})"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.invalid_default_arg!
|
12
|
+
raise ArgumentError, INVALID_DEFAULT_ARG
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(arg, object = UNDEFINED, label: nil)
|
16
|
+
if UNDEFINED == object
|
17
|
+
# Will be used when the exception was raised with a message. e.g:
|
18
|
+
# raise Kind::Error, "some message"
|
19
|
+
super(arg)
|
20
|
+
else
|
21
|
+
label_text = label ? "#{label}: " : ''
|
22
|
+
|
23
|
+
super("#{label_text}#{object.inspect} expected to be a kind of #{arg}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private_constant :INVALID_DEFAULT_ARG
|
28
|
+
end
|
29
|
+
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Kind
|
3
4
|
Undefined = Object.new.tap do |undefined|
|
4
5
|
def undefined.inspect
|
5
6
|
@inspect ||= 'Kind::Undefined'.freeze
|
6
7
|
end
|
8
|
+
undefined.inspect
|
9
|
+
|
10
|
+
def undefined.empty?
|
11
|
+
true
|
12
|
+
end
|
7
13
|
|
8
14
|
def undefined.to_s
|
9
15
|
inspect
|
@@ -23,7 +29,6 @@ module Kind
|
|
23
29
|
default.respond_to?(:call) ? default.call : default
|
24
30
|
end
|
25
31
|
|
26
|
-
undefined.inspect
|
27
32
|
undefined.freeze
|
28
33
|
end
|
29
34
|
end
|
data/lib/kind/dig.rb
CHANGED
@@ -1,23 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/empty'
|
5
|
+
require 'kind/presence'
|
6
|
+
|
3
7
|
module Kind
|
4
8
|
module Dig
|
5
9
|
extend self
|
6
10
|
|
7
|
-
def call(data, keys)
|
8
|
-
return unless keys.is_a?(::Array)
|
9
|
-
|
11
|
+
def call!(data, keys = Empty::ARRAY) # :nodoc
|
10
12
|
keys.reduce(data) do |memo, key|
|
11
13
|
value = get(memo, key)
|
12
14
|
|
13
|
-
break if KIND.
|
15
|
+
break if KIND.nil_or_undefined?(value)
|
14
16
|
|
15
17
|
value
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
def call(data, *input)
|
22
|
+
args = input.size == 1 && input[0].kind_of?(::Array) ? input[0] : input
|
23
|
+
|
24
|
+
result = call!(data, args)
|
25
|
+
|
26
|
+
return result unless block_given?
|
27
|
+
|
28
|
+
yield(result) unless KIND.nil_or_undefined?(result)
|
29
|
+
end
|
30
|
+
|
31
|
+
def presence(*args, &block)
|
32
|
+
Presence.(call(*args, &block))
|
33
|
+
end
|
34
|
+
|
19
35
|
def [](*keys)
|
20
|
-
->(data) { call(data, keys) }
|
36
|
+
->(data) { call!(data, keys) }
|
21
37
|
end
|
22
38
|
|
23
39
|
private
|
data/lib/kind/either.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
module Either
|
7
|
+
require 'kind/either/monad'
|
8
|
+
require 'kind/either/left'
|
9
|
+
require 'kind/either/right'
|
10
|
+
require 'kind/either/methods'
|
11
|
+
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def new(value)
|
15
|
+
Right[value]
|
16
|
+
end
|
17
|
+
|
18
|
+
alias_method :[], :new
|
19
|
+
|
20
|
+
def self.from
|
21
|
+
result = yield
|
22
|
+
|
23
|
+
Either::Monad === result ? result : Either::Right[result]
|
24
|
+
rescue StandardError => e
|
25
|
+
Either::Left[e]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
extend Either::Methods
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Either::Left < Either::Monad
|
5
|
+
def left?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_or(default = UNDEFINED, &block)
|
10
|
+
Error.invalid_default_arg! if UNDEFINED == default && !block
|
11
|
+
|
12
|
+
UNDEFINED != default ? default : block.call
|
13
|
+
end
|
14
|
+
|
15
|
+
def map(&_)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
alias_method :map!, :map
|
20
|
+
alias_method :then, :map
|
21
|
+
alias_method :then!, :map
|
22
|
+
alias_method :and_then, :map
|
23
|
+
alias_method :and_then!, :map
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
'#<%s value=%p>' % ['Kind::Left', value]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Either::Methods
|
5
|
+
def Left(value)
|
6
|
+
Either::Left[value]
|
7
|
+
end
|
8
|
+
|
9
|
+
def Right(value)
|
10
|
+
Either::Right[value]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
base.send(:private, :Left, :Right)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Either::Monad
|
5
|
+
require 'kind/either/monad/wrapper'
|
6
|
+
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
singleton_class.send(:alias_method, :[], :new)
|
10
|
+
|
11
|
+
def initialize(value)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def left?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def right?
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def value_or(_method_name = UNDEFINED, &block)
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def map(&_)
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :map!, :map
|
32
|
+
alias_method :then, :map
|
33
|
+
alias_method :then!, :map
|
34
|
+
alias_method :and_then, :map
|
35
|
+
alias_method :and_then!, :map
|
36
|
+
|
37
|
+
def on
|
38
|
+
monad = Wrapper.new(self)
|
39
|
+
|
40
|
+
yield(monad)
|
41
|
+
|
42
|
+
monad.output
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_right(matcher = UNDEFINED)
|
46
|
+
yield(value) if right? && either?(matcher)
|
47
|
+
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def on_left(matcher = UNDEFINED)
|
52
|
+
yield(value) if left? && either?(matcher)
|
53
|
+
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def either?(matcher)
|
58
|
+
UNDEFINED == matcher || matcher === value
|
59
|
+
end
|
60
|
+
|
61
|
+
def ===(monad)
|
62
|
+
self.class === monad && self.value === monad.value
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
require 'kind/monad'
|
5
|
+
|
6
|
+
class Either::Monad::Wrapper < Kind::Monad::Wrapper
|
7
|
+
def left(matcher = UNDEFINED)
|
8
|
+
return if @monad.right? || output?
|
9
|
+
|
10
|
+
@output = yield(@monad.value) if @monad.either?(matcher)
|
11
|
+
end
|
12
|
+
|
13
|
+
def right(matcher = UNDEFINED)
|
14
|
+
return if @monad.left? || output?
|
15
|
+
|
16
|
+
@output = yield(@monad.value) if @monad.either?(matcher)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Either::Right < Either::Monad
|
5
|
+
def right?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def value_or(_default = UNDEFINED, &block)
|
10
|
+
@value
|
11
|
+
end
|
12
|
+
|
13
|
+
def map(&fn)
|
14
|
+
map!(&fn)
|
15
|
+
rescue Kind::Monad::Error => e
|
16
|
+
raise e
|
17
|
+
rescue StandardError => e
|
18
|
+
Either::Left[e]
|
19
|
+
end
|
20
|
+
|
21
|
+
def map!(&fn)
|
22
|
+
monad = fn.call(@value)
|
23
|
+
|
24
|
+
return monad if Either::Monad === monad
|
25
|
+
|
26
|
+
raise Kind::Monad::Error.new('Kind::Right | Kind::Left', monad)
|
27
|
+
end
|
28
|
+
|
29
|
+
alias_method :then, :map
|
30
|
+
alias_method :then!, :map!
|
31
|
+
alias_method :and_then, :map
|
32
|
+
alias_method :and_then!, :map!
|
33
|
+
|
34
|
+
def inspect
|
35
|
+
'#<%s value=%p>' % ['Kind::Right', value]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/kind/empty.rb
CHANGED
data/lib/kind/enum.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require 'kind/basic'
|
5
|
+
|
6
|
+
module Kind
|
7
|
+
module Enum
|
8
|
+
require 'kind/enum/item'
|
9
|
+
require 'kind/enum/methods'
|
10
|
+
|
11
|
+
extend self
|
12
|
+
|
13
|
+
def values(input)
|
14
|
+
enum_module = ::Module.new
|
15
|
+
|
16
|
+
enum_items =
|
17
|
+
case input
|
18
|
+
when ::Hash then create_from_hash(input)
|
19
|
+
when ::Array then create_from_array(input)
|
20
|
+
else raise ArgumentError, 'use an array or hash to define a Kind::Enum'
|
21
|
+
end
|
22
|
+
|
23
|
+
enum_items.each { |item| enum_module.const_set(item.name, item) }
|
24
|
+
|
25
|
+
enum_map = enum_items.each_with_object({}) do |item, memo|
|
26
|
+
memo[item.to_s] = item
|
27
|
+
memo[item.value] = item
|
28
|
+
memo[item.to_sym] = item
|
29
|
+
end
|
30
|
+
|
31
|
+
enum_module.const_set(:ENUM__MAP, enum_map)
|
32
|
+
enum_module.const_set(:ENUM__HASH, enum_items.map(&:to_ary).to_h.freeze)
|
33
|
+
enum_module.const_set(:ENUM__KEYS, ::Set.new(enum_items.map(&:key)).freeze)
|
34
|
+
enum_module.const_set(:ENUM__VALS, ::Set.new(enum_items.map(&:value)).freeze)
|
35
|
+
enum_module.const_set(:ENUM__REFS, ::Set.new(enum_map.keys))
|
36
|
+
enum_module.const_set(:ENUM__ITEMS, enum_items.freeze)
|
37
|
+
|
38
|
+
enum_module.send(:private_constant, :ENUM__MAP, :ENUM__HASH, :ENUM__KEYS,
|
39
|
+
:ENUM__VALS, :ENUM__REFS, :ENUM__ITEMS)
|
40
|
+
|
41
|
+
enum_module.module_eval(METHODS)
|
42
|
+
|
43
|
+
enum_module.extend(enum_module)
|
44
|
+
enum_module
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def create_from_hash(input)
|
50
|
+
input.map { |key, value| build_item(key, value) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_from_array(input)
|
54
|
+
input.map.with_index { |key, index| build_item(key, index) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_item(key, value)
|
58
|
+
return Item.new(key, value) if key.respond_to?(:to_sym)
|
59
|
+
|
60
|
+
raise ArgumentError, 'use a string or symbol to define a Kind::Enum item'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|