kind 1.7.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.sh +20 -0
- data/.travis.yml +3 -1
- data/Gemfile +31 -6
- data/README.md +549 -55
- data/kind.gemspec +2 -2
- data/lib/kind.rb +59 -34
- data/lib/kind/active_model/kind_validator.rb +96 -0
- data/lib/kind/active_model/validation.rb +7 -0
- data/lib/kind/checker.rb +41 -3
- data/lib/kind/error.rb +12 -2
- data/lib/kind/maybe.rb +36 -11
- data/lib/kind/types.rb +14 -3
- data/lib/kind/undefined.rb +1 -1
- data/lib/kind/validator.rb +40 -0
- data/lib/kind/version.rb +1 -1
- data/test.sh +11 -0
- metadata +9 -4
data/lib/kind/maybe.rb
CHANGED
@@ -4,7 +4,7 @@ module Kind
|
|
4
4
|
module Maybe
|
5
5
|
module Value
|
6
6
|
def self.none?(value)
|
7
|
-
value
|
7
|
+
value.nil? || Undefined == value
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.some?(value)
|
@@ -16,7 +16,7 @@ module Kind
|
|
16
16
|
attr_reader :value
|
17
17
|
|
18
18
|
def initialize(value)
|
19
|
-
@value = value
|
19
|
+
@value = value.kind_of?(Result) ? value.value : value
|
20
20
|
end
|
21
21
|
|
22
22
|
def value_or(method_name = Undefined, &block)
|
@@ -42,9 +42,9 @@ module Kind
|
|
42
42
|
INVALID_DEFAULT_ARG = 'the default value must be defined as an argument or block'.freeze
|
43
43
|
|
44
44
|
def value_or(default = Undefined, &block)
|
45
|
-
raise ArgumentError, INVALID_DEFAULT_ARG if
|
45
|
+
raise ArgumentError, INVALID_DEFAULT_ARG if Undefined == default && !block
|
46
46
|
|
47
|
-
|
47
|
+
Undefined != default ? default : block.call
|
48
48
|
end
|
49
49
|
|
50
50
|
def none?; true; end
|
@@ -56,7 +56,7 @@ module Kind
|
|
56
56
|
alias_method :then, :map
|
57
57
|
|
58
58
|
def try(method_name = Undefined, &block)
|
59
|
-
Kind.of.Symbol(method_name) if
|
59
|
+
Kind.of.Symbol(method_name) if Undefined != method_name
|
60
60
|
|
61
61
|
nil
|
62
62
|
end
|
@@ -79,18 +79,19 @@ module Kind
|
|
79
79
|
def map(&fn)
|
80
80
|
result = fn.call(@value)
|
81
81
|
|
82
|
-
return
|
83
|
-
return
|
82
|
+
return result if Maybe::None === result
|
83
|
+
return NONE_WITH_NIL_VALUE if result.nil?
|
84
|
+
return NONE_WITH_UNDEFINED_VALUE if Undefined == result
|
84
85
|
|
85
86
|
Some.new(result)
|
86
87
|
end
|
87
88
|
|
88
89
|
alias_method :then, :map
|
89
90
|
|
90
|
-
def try(method_name = Undefined, &block)
|
91
|
-
fn =
|
91
|
+
def try(method_name = Undefined, *args, &block)
|
92
|
+
fn = Undefined == method_name ? block : Kind.of.Symbol(method_name).to_proc
|
92
93
|
|
93
|
-
result = fn.call(value)
|
94
|
+
result = args.empty? ? fn.call(value) : fn.call(*args.unshift(value))
|
94
95
|
|
95
96
|
return result if Maybe::Value.some?(result)
|
96
97
|
end
|
@@ -98,13 +99,37 @@ module Kind
|
|
98
99
|
|
99
100
|
def self.new(value)
|
100
101
|
result_type = Maybe::Value.none?(value) ? None : Some
|
101
|
-
result_type.new(value
|
102
|
+
result_type.new(value)
|
102
103
|
end
|
103
104
|
|
104
105
|
def self.[](value);
|
105
106
|
new(value)
|
106
107
|
end
|
108
|
+
|
109
|
+
def self.none
|
110
|
+
NONE_WITH_NIL_VALUE
|
111
|
+
end
|
112
|
+
|
113
|
+
VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
|
114
|
+
|
115
|
+
private_constant :VALUE_CANT_BE_NONE
|
116
|
+
|
117
|
+
def self.some(value)
|
118
|
+
return Maybe::Some.new(value) if Value.some?(value)
|
119
|
+
|
120
|
+
raise ArgumentError, VALUE_CANT_BE_NONE
|
121
|
+
end
|
107
122
|
end
|
108
123
|
|
109
124
|
Optional = Maybe
|
125
|
+
|
126
|
+
None = Maybe.none
|
127
|
+
|
128
|
+
def self.None
|
129
|
+
Kind::None
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.Some(value)
|
133
|
+
Maybe.some(value)
|
134
|
+
end
|
110
135
|
end
|
data/lib/kind/types.rb
CHANGED
@@ -10,15 +10,25 @@ module Kind
|
|
10
10
|
def self.%{method_name}(object = Undefined, options = Empty::HASH)
|
11
11
|
default = options[:or]
|
12
12
|
|
13
|
-
return Kind::Of::%{kind_name} if
|
13
|
+
return Kind::Of::%{kind_name} if Undefined == object && default.nil?
|
14
14
|
|
15
|
-
Kind::Of
|
15
|
+
is_instance = Kind::Of::%{kind_name}.__is_instance__(object)
|
16
|
+
|
17
|
+
return object if is_instance
|
18
|
+
|
19
|
+
Kind::Of.(::%{kind_name_to_check}, object && default ? default : object || default)
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
|
23
|
+
KIND_OF_IS = <<-RUBY
|
24
|
+
def self.%{method_name}?(*args)
|
25
|
+
Kind::Of::%{kind_name}.instance?(*args)
|
16
26
|
end
|
17
27
|
RUBY
|
18
28
|
|
19
29
|
KIND_IS = <<-RUBY
|
20
30
|
def self.%{method_name}(value = Undefined)
|
21
|
-
return Kind::Is::%{kind_name} if
|
31
|
+
return Kind::Is::%{kind_name} if Undefined == value
|
22
32
|
|
23
33
|
Kind::Is.__call__(::%{kind_name_to_check}, value)
|
24
34
|
end
|
@@ -93,6 +103,7 @@ module Kind
|
|
93
103
|
|
94
104
|
kind_of_mod.instance_eval(KIND_OF % params)
|
95
105
|
kind_of_mod.const_set(method_name, kind_checker)
|
106
|
+
kind_of_mod.instance_eval(KIND_OF_IS % params)
|
96
107
|
end
|
97
108
|
|
98
109
|
unless kind_is_mod.respond_to?(method_name)
|
data/lib/kind/undefined.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module Validator
|
5
|
+
DEFAULT_STRATEGIES = Set.new(%w[instance_of kind_of]).freeze
|
6
|
+
|
7
|
+
class InvalidDefinition < ArgumentError
|
8
|
+
OPTIONS = 'Options to define one: :of, :is, :respond_to, :instance_of, :array_of or :array_with'.freeze
|
9
|
+
|
10
|
+
def initialize(attribute)
|
11
|
+
super "invalid type definition for :#{attribute} attribute. #{OPTIONS}"
|
12
|
+
end
|
13
|
+
|
14
|
+
private_constant :OPTIONS
|
15
|
+
end
|
16
|
+
|
17
|
+
class InvalidDefaultStrategy < ArgumentError
|
18
|
+
OPTIONS =
|
19
|
+
DEFAULT_STRATEGIES.map { |option| ":#{option}" }.join(', ')
|
20
|
+
|
21
|
+
def initialize(option)
|
22
|
+
super "#{option.inspect} is an invalid option. Please use one of these: #{OPTIONS}"
|
23
|
+
end
|
24
|
+
|
25
|
+
private_constant :OPTIONS
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.default_strategy
|
29
|
+
@default_strategy ||= :kind_of
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.default_strategy=(option)
|
33
|
+
if DEFAULT_STRATEGIES.member?(String(option))
|
34
|
+
@default_strategy = option.to_sym
|
35
|
+
else
|
36
|
+
raise InvalidDefaultStrategy.new(option)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/kind/version.rb
CHANGED
data/test.sh
ADDED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: A simple type system (at runtime) for Ruby - free of dependencies.
|
14
14
|
email:
|
15
15
|
- rodrigo.serradura@gmail.com
|
16
16
|
executables: []
|
@@ -18,6 +18,7 @@ extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- ".gitignore"
|
21
|
+
- ".travis.sh"
|
21
22
|
- ".travis.yml"
|
22
23
|
- CODE_OF_CONDUCT.md
|
23
24
|
- Gemfile
|
@@ -28,6 +29,8 @@ files:
|
|
28
29
|
- bin/setup
|
29
30
|
- kind.gemspec
|
30
31
|
- lib/kind.rb
|
32
|
+
- lib/kind/active_model/kind_validator.rb
|
33
|
+
- lib/kind/active_model/validation.rb
|
31
34
|
- lib/kind/checker.rb
|
32
35
|
- lib/kind/empty.rb
|
33
36
|
- lib/kind/error.rb
|
@@ -36,7 +39,9 @@ files:
|
|
36
39
|
- lib/kind/of.rb
|
37
40
|
- lib/kind/types.rb
|
38
41
|
- lib/kind/undefined.rb
|
42
|
+
- lib/kind/validator.rb
|
39
43
|
- lib/kind/version.rb
|
44
|
+
- test.sh
|
40
45
|
homepage: https://github.com/serradura/kind
|
41
46
|
licenses:
|
42
47
|
- MIT
|
@@ -61,5 +66,5 @@ requirements: []
|
|
61
66
|
rubygems_version: 3.0.6
|
62
67
|
signing_key:
|
63
68
|
specification_version: 4
|
64
|
-
summary:
|
69
|
+
summary: A simple type system (at runtime) for Ruby.
|
65
70
|
test_files: []
|