kind 5.2.0 → 5.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e522116072626ac76a87df9351e292f31a0f96cefa1bbc07d9e83c50198a25a8
4
- data.tar.gz: 529cd2b05c6767c2553ce9fa1e157cef564e7fc0092874839c6714e0df797240
3
+ metadata.gz: b826449cc89c4cd8dc3d58694a37914f7de37cb7000a2ba534ffa914f10f7677
4
+ data.tar.gz: e2ed88bcf83d332de58a8516533a58f858494e7ac2ea60f58517e08cd11066c9
5
5
  SHA512:
6
- metadata.gz: 206cacdc59d7288b4db022dac5c45fe95649845bb0093fbee14eb86444b145651407847b380b831c8267190f1d515b7c775810549c6ee73df61059f1d484129a
7
- data.tar.gz: ff97ce3f297254fd3932b853588c6d1f47a931c16065b5961e06fc4fe219ec6672db0fe16e1d0ffef4b34d25c6e9c35cc28c655b3cc539b519e916f60162ba04
6
+ metadata.gz: ac5f74a2ba85be82a6b9709745069047105ccdf8aacadbabdb7e96f66ff007dd0e7ce8e2001df206614c3bf852cb95f3c9d21d2f203490a39070a92bb2250afd
7
+ data.tar.gz: 14b4f8b747a25b9c9535f40972dcfbc07116f97051090616053c663dbfe71cc5b8771bc5899da4e51a77168acb18a18a8c0b898a37c6730397d5c3a4afdc340b
data/.travis.sh CHANGED
@@ -21,6 +21,8 @@ function run_basic_tests {
21
21
  eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/{functional/*_test,functional_test}.rb'"
22
22
  eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/either/*_test.rb'"
23
23
  eval "KIND_BASIC=t $bundle_cmd exec rake test TEST='test/kind/result/*_test.rb'"
24
+
25
+ eval "KIND_STRICT=t $bundle_cmd exec rake test TEST='test/kind/strict_disabled_test.rb'"
24
26
  }
25
27
 
26
28
  function run_with_bundler {
data/CHANGELOG.md CHANGED
@@ -3,73 +3,75 @@
3
3
  This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the recommendations of [keepachangelog.com](http://keepachangelog.com/).
4
4
 
5
5
  - [Unreleased](#unreleased)
6
- - [5.2.0 (2021-03-17)](#520-2021-03-17)
6
+ - [5.3.0 (2021-03-23)](#530-2021-03-23)
7
7
  - [Added](#added)
8
+ - [5.2.0 (2021-03-17)](#520-2021-03-17)
9
+ - [Added](#added-1)
8
10
  - [Deprecated](#deprecated)
9
11
  - [Changes](#changes)
10
12
  - [5.1.0 (2021-02-23)](#510-2021-02-23)
11
- - [Added](#added-1)
13
+ - [Added](#added-2)
12
14
  - [Deprecated](#deprecated-1)
13
15
  - [5.0.0 (2021-02-22)](#500-2021-02-22)
14
16
  - [Breaking Changes](#breaking-changes)
15
17
  - [Removed](#removed)
16
18
  - [4.1.0 (2021-02-22)](#410-2021-02-22)
17
- - [Added](#added-2)
18
- - [4.0.0 (2021-02-22)](#400-2021-02-22)
19
19
  - [Added](#added-3)
20
+ - [4.0.0 (2021-02-22)](#400-2021-02-22)
21
+ - [Added](#added-4)
20
22
  - [Deprecated](#deprecated-2)
21
23
  - [Fixed](#fixed)
22
24
  - [3.1.0 (2020-07-08)](#310-2020-07-08)
23
- - [Added](#added-4)
25
+ - [Added](#added-5)
24
26
  - [3.0.0 (2020-06-25)](#300-2020-06-25)
25
27
  - [Breaking Changes](#breaking-changes-1)
26
- - [Added](#added-5)
27
- - [2.3.0 (2020-06-24)](#230-2020-06-24)
28
28
  - [Added](#added-6)
29
- - [2.2.0 (2020-06-23)](#220-2020-06-23)
29
+ - [2.3.0 (2020-06-24)](#230-2020-06-24)
30
30
  - [Added](#added-7)
31
- - [2.1.0 (2020-05-12)](#210-2020-05-12)
31
+ - [2.2.0 (2020-06-23)](#220-2020-06-23)
32
32
  - [Added](#added-8)
33
+ - [2.1.0 (2020-05-12)](#210-2020-05-12)
34
+ - [Added](#added-9)
33
35
  - [Breaking Changes](#breaking-changes-2)
34
36
  - [2.0.0 (2020-05-07)](#200-2020-05-07)
35
- - [Added](#added-9)
37
+ - [Added](#added-10)
36
38
  - [Breaking Changes](#breaking-changes-3)
37
39
  - [Removed](#removed-1)
38
40
  - [1.9.0 (2020-05-06)](#190-2020-05-06)
39
- - [Added](#added-10)
40
- - [1.8.0 (2020-05-03)](#180-2020-05-03)
41
41
  - [Added](#added-11)
42
+ - [1.8.0 (2020-05-03)](#180-2020-05-03)
43
+ - [Added](#added-12)
42
44
  - [1.7.0 (2020-05-03)](#170-2020-05-03)
43
45
  - [Fixed](#fixed-1)
44
46
  - [1.6.0 (2020-04-17)](#160-2020-04-17)
45
- - [Added](#added-12)
47
+ - [Added](#added-13)
46
48
  - [Changes](#changes-1)
47
49
  - [1.5.0 (2020-04-12)](#150-2020-04-12)
48
- - [Added](#added-13)
49
- - [1.4.0 (2020-04-12)](#140-2020-04-12)
50
50
  - [Added](#added-14)
51
- - [1.3.0 (2020-04-12)](#130-2020-04-12)
51
+ - [1.4.0 (2020-04-12)](#140-2020-04-12)
52
52
  - [Added](#added-15)
53
- - [1.2.0 (2020-04-12)](#120-2020-04-12)
53
+ - [1.3.0 (2020-04-12)](#130-2020-04-12)
54
54
  - [Added](#added-16)
55
- - [1.1.0 (2020-04-09)](#110-2020-04-09)
55
+ - [1.2.0 (2020-04-12)](#120-2020-04-12)
56
56
  - [Added](#added-17)
57
+ - [1.1.0 (2020-04-09)](#110-2020-04-09)
58
+ - [Added](#added-18)
57
59
  - [Fixed](#fixed-2)
58
60
  - [1.0.0 (2020-03-16)](#100-2020-03-16)
59
- - [Added](#added-18)
60
- - [0.6.0 (2020-01-06)](#060-2020-01-06)
61
61
  - [Added](#added-19)
62
- - [0.5.0 (2020-01-04)](#050-2020-01-04)
62
+ - [0.6.0 (2020-01-06)](#060-2020-01-06)
63
63
  - [Added](#added-20)
64
- - [0.4.0 (2020-01-03)](#040-2020-01-03)
64
+ - [0.5.0 (2020-01-04)](#050-2020-01-04)
65
65
  - [Added](#added-21)
66
- - [0.3.0 (2020-01-03)](#030-2020-01-03)
66
+ - [0.4.0 (2020-01-03)](#040-2020-01-03)
67
67
  - [Added](#added-22)
68
+ - [0.3.0 (2020-01-03)](#030-2020-01-03)
69
+ - [Added](#added-23)
68
70
  - [Breaking Changes](#breaking-changes-4)
69
71
  - [0.2.0 (2020-01-02)](#020-2020-01-02)
70
- - [Added](#added-23)
71
- - [0.1.0 (2019-12-26)](#010-2019-12-26)
72
72
  - [Added](#added-24)
73
+ - [0.1.0 (2019-12-26)](#010-2019-12-26)
74
+ - [Added](#added-25)
73
75
 
74
76
  ## Unreleased
75
77
 
@@ -81,6 +83,45 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
81
83
  ### Fixed
82
84
  -->
83
85
 
86
+ 5.3.0 (2021-03-23)
87
+ ------------------
88
+
89
+ ### Added
90
+
91
+ * [#53](https://github.com/serradura/kind/pull/53) - Allow `Kind::Result#map` and `Kind::Result#map!` receive a callable as an argument.
92
+
93
+ * [#53](https://github.com/serradura/kind/pull/53) - Add `|` and `>>` as an alias of `Kind::Result#map!`.
94
+
95
+ * [#53](https://github.com/serradura/kind/pull/53) - Add step adapters for `Kind::Action` and `Kind::Functional::Action`. This is the list of methods: `Step`, `Map`, `Try`, `Tee`, `Check`.
96
+ ```ruby
97
+ module CreateUser
98
+ extend Kind::Functional::Action
99
+
100
+ def call!(input)
101
+ Step!(:validate, input) \
102
+ | Step(:create)
103
+ end
104
+
105
+ private
106
+
107
+ def validate(input)
108
+ # returns Success(valid_data) or Failure(validation)
109
+ end
110
+
111
+ def create(input)
112
+ # returns Success(user)
113
+ end
114
+ end
115
+ ```
116
+
117
+ * [#53](https://github.com/serradura/kind/pull/53) - Add `kind/strict/disabled` to turn off all of the strict validations and optimize the runtime. Use case: As strict validation is useful in development, this mechanism could be used to optimize the runtime in production. List of methods that will be disabled:
118
+ * `Kind.of()`
119
+ * `Kind.of_class()`
120
+ * `Kind.of_module()`
121
+ * `Kind.of_module_or_class()`
122
+ * `Kind::<Type>[1]`
123
+ * `Kind::NotNil[1]`
124
+
84
125
  5.2.0 (2021-03-17)
85
126
  ------------------
86
127
 
data/README.md CHANGED
@@ -40,7 +40,7 @@ One of the goals of this project is to do simple type checking like `"some strin
40
40
  Version | Documentation
41
41
  ---------- | -------------
42
42
  unreleased | https://github.com/serradura/kind/blob/main/README.md
43
- 5.2.0 | https://github.com/serradura/kind/blob/v5.x/README.md
43
+ 5.3.0 | https://github.com/serradura/kind/blob/v5.x/README.md
44
44
  4.1.0 | https://github.com/serradura/kind/blob/v4.x/README.md
45
45
  3.1.0 | https://github.com/serradura/kind/blob/v3.x/README.md
46
46
  2.3.0 | https://github.com/serradura/kind/blob/v2.x/README.md
@@ -123,7 +123,7 @@ unreleased | https://github.com/serradura/kind/blob/main/README.md
123
123
  | kind | branch | ruby | activemodel |
124
124
  | -------------- | ------- | -------- | -------------- |
125
125
  | unreleased | main | >= 2.1.0 | >= 3.2, <= 6.1 |
126
- | 5.2.0 | v5.x | >= 2.1.0 | >= 3.2, <= 6.1 |
126
+ | 5.3.0 | v5.x | >= 2.1.0 | >= 3.2, <= 6.1 |
127
127
  | 4.1.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
128
128
  | 3.1.0 | v3.x | >= 2.2.0 | >= 3.2, <= 6.1 |
129
129
  | 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module ACTION_STEPS
5
+ private
6
+
7
+ def Check(mthod); ->(value) { __Check(thod, value) }; end
8
+ def Step(mthod); ->(value) { __Step(mthod, value) }; end
9
+ def Map(mthod); ->(value) { __Map(mthod, value) }; end
10
+ def Tee(mthod); ->(value) { __Tee(mthod, value) }; end
11
+ def Try(mthod, opt = Empty::HASH)
12
+ ->(value) { __Try(mthod, value, opt) }
13
+ end
14
+
15
+ def Check!(mthod, value); __Check(mthod, value); end
16
+ def Step!(mthod, value); __Step(mthod, value); end
17
+ def Map!(mthod, value); __Map(mthod, value); end
18
+ def Tee!(mthod, value); __Tee(mthod, value); end
19
+ def Try!(mthod, value, opt = Empty::HASH); __Try(mthod, value, opt); end
20
+
21
+ def __Check(mthod, value) # :nodoc:
22
+ __resolve_step(mthod, value) ? Success(mthod, value) : Failure(mthod, value)
23
+ end
24
+
25
+ def __Step(mthod, value) # :nodoc:
26
+ __resolve_step(mthod, value)
27
+ end
28
+
29
+ def __Map(mthod, value) # :nodoc:
30
+ Success(mthod, __resolve_step(mthod, value))
31
+ end
32
+
33
+ def __Tee(mthod, value) # :nodoc:
34
+ __resolve_step(mthod, value)
35
+
36
+ Success(mthod, value)
37
+ end
38
+
39
+ def __Try(mthod, value, opt = Empty::HASH) # :nodoc:
40
+ begin
41
+ Success(mthod, __resolve_step(mthod, value))
42
+ rescue opt.fetch(:catch, StandardError) => e
43
+ Failure(mthod, __map_step_exception(e))
44
+ end
45
+ end
46
+
47
+ def __resolve_step(mthod, value) # :nodoc:
48
+ send(mthod, value)
49
+ end
50
+
51
+ def __map_step_exception(value) # :nodoc:
52
+ value
53
+ end
54
+ end
55
+
56
+ private_constant :ACTION_STEPS
57
+ end
@@ -8,7 +8,7 @@ module Kind
8
8
  extend self
9
9
 
10
10
  def name!(name)
11
- KIND.of!(::Symbol, name)
11
+ STRICT.kind_of(::Symbol, name)
12
12
  end
13
13
 
14
14
  def value(kind, default, visibility = :private)
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kind/__lib__/strict'
4
+
3
5
  module Kind
4
6
  module KIND
5
7
  extend self
6
8
 
7
- def null?(value) # :nodoc:
9
+ def nil_or_undefined?(value) # :nodoc:
8
10
  value.nil? || Undefined == value
9
11
  end
10
12
 
@@ -14,28 +16,6 @@ module Kind
14
16
  values.empty? ? of_kind : values.all?(&of_kind)
15
17
  end
16
18
 
17
- def of!(kind, value, kind_name = nil) # :nodoc:
18
- return value if kind === value
19
-
20
- error!(kind_name || kind.name, value)
21
- end
22
-
23
- def error!(kind_name, value, label = nil) # :nodoc:
24
- raise Error.new(kind_name, value, label: label)
25
- end
26
-
27
- def of_class?(value) # :nodoc:
28
- value.kind_of?(::Class)
29
- end
30
-
31
- def of_module?(value) # :nodoc:
32
- ::Module == value || (value.kind_of?(::Module) && !of_class?(value))
33
- end
34
-
35
- def of_module_or_class!(value) # :nodoc:
36
- of!(::Module, value, 'Module/Class')
37
- end
38
-
39
19
  def respond_to!(method_name, value) # :nodoc:
40
20
  return value if value.respond_to?(method_name)
41
21
 
@@ -51,15 +31,15 @@ module Kind
51
31
  end
52
32
 
53
33
  def is?(expected, value) # :nodoc:
54
- is(of_module_or_class!(expected), value)
34
+ is(STRICT.module_or_class(expected), value)
55
35
  end
56
36
 
57
37
  private
58
38
 
59
39
  def is(expected_kind, value) # :nodoc:
60
- kind = of_module_or_class!(value)
40
+ kind = STRICT.module_or_class(value)
61
41
 
62
- if of_class?(kind)
42
+ if OF.class?(kind)
63
43
  kind <= expected_kind || expected_kind == ::Class
64
44
  else
65
45
  kind == expected_kind || kind.kind_of?(expected_kind)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module OF
5
+ extend self
6
+
7
+ def class?(value) # :nodoc:
8
+ value.kind_of?(::Class)
9
+ end
10
+
11
+ def module?(value) # :nodoc:
12
+ ::Module == value || (value.kind_of?(::Module) && !class?(value))
13
+ end
14
+ end
15
+
16
+ private_constant :OF
17
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kind/__lib__/of'
4
+
5
+ module Kind
6
+ module STRICT
7
+ extend self
8
+
9
+ def error(kind_name, value, label = nil) # :nodoc:
10
+ raise Error.new(kind_name, value, label: label)
11
+ end
12
+
13
+ def object_is_a(kind, value, label = nil) # :nodoc:
14
+ return value if kind === value
15
+
16
+ error(kind.name, value, label)
17
+ end
18
+
19
+ def kind_of(kind, value, kind_name = nil) # :nodoc:
20
+ return value if kind === value
21
+
22
+ error(kind_name || kind.name, value)
23
+ end
24
+
25
+ def module_or_class(value) # :nodoc:
26
+ kind_of(::Module, value, 'Module/Class')
27
+ end
28
+
29
+ def class!(value) # :nodoc:
30
+ kind_of(::Class, value)
31
+ end
32
+
33
+ def module!(value) # :nodoc:
34
+ return value if OF.module?(value)
35
+
36
+ error('Module', value)
37
+ end
38
+
39
+ def not_nil(value, label) # :nodoc:
40
+ return value unless value.nil?
41
+
42
+ label_text = label ? "#{label}: " : ''
43
+
44
+ raise Error.new("#{label_text}expected to not be nil")
45
+ end
46
+ end
47
+
48
+ private_constant :STRICT
49
+ end
data/lib/kind/action.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'kind/basic'
4
+ require 'kind/empty'
4
5
  require 'kind/result'
5
6
  require 'kind/immutable_attributes'
7
+ require 'kind/__lib__/action_steps'
6
8
 
7
9
  module Kind
8
10
  module Action
@@ -20,6 +22,8 @@ module Kind
20
22
  'end'
21
23
  ].join("\n").freeze
22
24
 
25
+ private_constant :CALL_TMPL
26
+
23
27
  module ClassMethods
24
28
  include ImmutableAttributes::ClassMethods
25
29
 
@@ -71,21 +75,52 @@ module Kind
71
75
  end
72
76
  end
73
77
 
78
+ module StepAdapters
79
+ private
80
+
81
+ def Check!(mthod); __Check(mthod, Empty::HASH); end
82
+ def Step!(mthod); __Step(mthod, Empty::HASH); end
83
+ def Map!(mthod); __Map(mthod, Empty::HASH); end
84
+ def Tee!(_mthod); raise NotImplementedError; end
85
+ def Try!(mthod, opt = Empty::HASH); __Try(mthod, Empty::HASH, opt); end
86
+
87
+ def __resolve_step(method_name, value)
88
+ m = method(method_name)
89
+ m.arity > 0 ? m.call(value) : m.call
90
+ end
91
+
92
+ def __map_step_exception(value)
93
+ { exception: value }
94
+ end
95
+ end
96
+
97
+ private_constant :StepAdapters
98
+
74
99
  def self.included(base)
75
- KIND.of!(::Class, base).extend(ClassMethods)
100
+ Kind.of_class(base).extend(ClassMethods)
76
101
 
102
+ base.send(:include, ACTION_STEPS)
103
+ base.send(:include, StepAdapters)
77
104
  base.send(:include, ImmutableAttributes::Reader)
78
105
  end
79
106
 
80
107
  include ImmutableAttributes::Initializer
81
108
 
109
+ def inspect
110
+ '#<%s attributes=%p nil_attributes=%p>' % [self.class.name, attributes, nil_attributes]
111
+ end
112
+
82
113
  private
83
114
 
84
115
  def Failure(arg1 = UNDEFINED, arg2 = UNDEFINED)
116
+ arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
117
+
85
118
  Result::Failure[arg1, arg2, value_must_be_a: ::Hash]
86
119
  end
87
120
 
88
121
  def Success(arg1 = UNDEFINED, arg2 = UNDEFINED)
122
+ arg1 = Empty::HASH if UNDEFINED == arg1 && UNDEFINED == arg2
123
+
89
124
  Result::Success[arg1, arg2, value_must_be_a: ::Hash]
90
125
  end
91
126
  end
data/lib/kind/basic.rb CHANGED
@@ -35,11 +35,11 @@ module Kind
35
35
  end
36
36
 
37
37
  def of_class?(value)
38
- KIND.of_class?(value)
38
+ OF.class?(value)
39
39
  end
40
40
 
41
41
  def of_module?(value)
42
- KIND.of_module?(value)
42
+ OF.module?(value)
43
43
  end
44
44
 
45
45
  def respond_to?(value, *method_names)
@@ -49,15 +49,21 @@ module Kind
49
49
  end
50
50
 
51
51
  def of(kind, value, label: nil)
52
- return value if kind === value
53
-
54
- KIND.error!(kind.name, value, label)
52
+ STRICT.object_is_a(kind, value, label)
55
53
  end
56
54
 
57
55
  alias_method :of!, :of
58
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
+
59
65
  def of_module_or_class(value)
60
- KIND.of_module_or_class!(value)
66
+ STRICT.module_or_class(value)
61
67
  end
62
68
 
63
69
  def respond_to(value, *method_names)
data/lib/kind/dig.rb CHANGED
@@ -12,7 +12,7 @@ module Kind
12
12
  keys.reduce(data) do |memo, key|
13
13
  value = get(memo, key)
14
14
 
15
- break if KIND.null?(value)
15
+ break if KIND.nil_or_undefined?(value)
16
16
 
17
17
  value
18
18
  end
@@ -25,7 +25,7 @@ module Kind
25
25
 
26
26
  return result unless block_given?
27
27
 
28
- yield(result) unless KIND.null?(result)
28
+ yield(result) unless KIND.nil_or_undefined?(result)
29
29
  end
30
30
 
31
31
  def presence(*args, &block)
data/lib/kind/function.rb CHANGED
@@ -17,9 +17,7 @@ module Kind
17
17
  end
18
18
 
19
19
  def self.extended(base)
20
- KIND.error!('Module', base) unless Kind.of_module?(base)
21
-
22
- base.extend(base)
20
+ base.extend(Kind.of_module(base))
23
21
  end
24
22
 
25
23
  def kind_function!
@@ -11,7 +11,7 @@ module Kind
11
11
  end
12
12
 
13
13
  def self.included(base)
14
- KIND.of!(::Class, base).send(:extend, ClassMethods)
14
+ Kind.of_class(base).send(:extend, ClassMethods)
15
15
  end
16
16
 
17
17
  module Behavior
@@ -22,7 +22,7 @@ module Kind
22
22
  end
23
23
 
24
24
  def initialize(arg = Empty::HASH)
25
- hash = KIND.of!(::Hash, arg)
25
+ hash = STRICT.kind_of(::Hash, arg)
26
26
 
27
27
  self.class.__dependencies__.each do |name, (kind, default, _visibility)|
28
28
  value_to_assign = ATTRIBUTES.value_to_assign!(kind, default, hash, name)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'kind/result'
4
4
  require 'kind/functional'
5
+ require 'kind/__lib__/action_steps'
5
6
 
6
7
  module Kind
7
8
  module Functional::Action
@@ -56,10 +57,12 @@ module Kind
56
57
  "#{CALL_TMPL % [call_tmpl_args, call_tmpl_args]}"
57
58
  )
58
59
 
59
- if KIND.of_module?(self)
60
+ if Kind.of_module?(self)
60
61
  self.send(:extend, Result::Methods)
62
+ self.send(:extend, ACTION_STEPS)
61
63
  else
62
64
  self.send(:include, Result::Methods)
65
+ self.send(:include, ACTION_STEPS)
63
66
  self.send(:include, Functional::Behavior)
64
67
 
65
68
  __dependencies__.freeze
@@ -72,15 +75,13 @@ module Kind
72
75
  end
73
76
 
74
77
  def self.included(base)
75
- KIND.of!(::Class, base).send(:extend, Functional::DependencyInjection)
78
+ Kind.of_class(base).send(:extend, Functional::DependencyInjection)
76
79
 
77
80
  base.send(:extend, Macros)
78
81
  end
79
82
 
80
83
  def self.extended(base)
81
- KIND.error!('Module', base) unless Kind.of_module?(base)
82
-
83
- base.send(:extend, base)
84
+ base.send(:extend, Kind.of_module(base))
84
85
  base.send(:extend, Macros)
85
86
  end
86
87
 
@@ -28,7 +28,7 @@ module Kind
28
28
  end
29
29
 
30
30
  def with_attributes(arg)
31
- hash = KIND.of!(::Hash, arg)
31
+ hash = STRICT.kind_of(::Hash, arg)
32
32
 
33
33
  self.class.new(@_____attrs.merge(hash))
34
34
  end
data/lib/kind/maybe.rb CHANGED
@@ -14,7 +14,7 @@ module Kind
14
14
  extend self
15
15
 
16
16
  def new(value)
17
- (::Exception === value || KIND.null?(value) ? None : Some)
17
+ (::Exception === value || KIND.nil_or_undefined?(value) ? None : Some)
18
18
  .new(value)
19
19
  end
20
20
 
@@ -25,7 +25,7 @@ module Kind
25
25
  alias_method :and_then!, :map!
26
26
 
27
27
  def try!(method_name = UNDEFINED, *args, &block)
28
- KIND.of!(::Symbol, method_name)if UNDEFINED != method_name
28
+ STRICT.kind_of(::Symbol, method_name)if UNDEFINED != method_name
29
29
 
30
30
  self
31
31
  end
@@ -6,12 +6,12 @@ require 'kind/presence'
6
6
  module Kind
7
7
  module Maybe
8
8
  class Some < Monad
9
- KindSymbol = ->(value) { KIND.of!(::Symbol, value) }
9
+ KindSymbol = ->(value) { STRICT.kind_of(::Symbol, value) }
10
10
 
11
11
  VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
12
12
 
13
13
  def self.[](value)
14
- return new(value) if !KIND.null?(value)
14
+ return new(value) if !KIND.nil_or_undefined?(value)
15
15
 
16
16
  raise ArgumentError, VALUE_CANT_BE_NONE
17
17
  end
@@ -57,7 +57,7 @@ module Kind
57
57
  fn.call(@value)
58
58
  end
59
59
 
60
- !result || KIND.null?(result) ? NONE_INSTANCE : self
60
+ !result || KIND.nil_or_undefined?(result) ? NONE_INSTANCE : self
61
61
  end
62
62
 
63
63
  alias_method :accept, :check
@@ -73,7 +73,7 @@ module Kind
73
73
  fn.call(@value)
74
74
  end
75
75
 
76
- result || KIND.null?(result) ? NONE_INSTANCE : self
76
+ result || KIND.nil_or_undefined?(result) ? NONE_INSTANCE : self
77
77
  end
78
78
 
79
79
  def try!(method_name = UNDEFINED, *args, &block)
@@ -120,7 +120,7 @@ module Kind
120
120
 
121
121
  def resolve(result)
122
122
  return result if Maybe::None === result
123
- return NONE_INSTANCE if KIND.null?(result)
123
+ return NONE_INSTANCE if KIND.nil_or_undefined?(result)
124
124
  return None.new(result) if ::Exception === result
125
125
 
126
126
  Some.new(result)
@@ -3,9 +3,7 @@
3
3
  module Kind
4
4
  module BasicObject
5
5
  def [](value, label: nil)
6
- return value if self === value
7
-
8
- KIND.error!(name, value, label)
6
+ STRICT.object_is_a(self, value, label)
9
7
  end
10
8
 
11
9
  def or_nil(value)
@@ -33,7 +31,7 @@ module Kind
33
31
  end
34
32
 
35
33
  def or_null(value) # :nodoc:
36
- KIND.null?(value) ? value : self[value]
34
+ KIND.nil_or_undefined?(value) ? value : self[value]
37
35
  end
38
36
 
39
37
  private
@@ -3,11 +3,7 @@
3
3
  module Kind
4
4
  module NotNil
5
5
  def self.[](value, label: nil)
6
- return value unless value.nil?
7
-
8
- label_text = label ? "#{label}: " : ''
9
-
10
- raise Error.new("#{label_text}expected to not be nil")
6
+ STRICT.not_nil(value, label)
11
7
  end
12
8
  end
13
9
  end
@@ -34,7 +34,7 @@ module Kind
34
34
  def initialize(kind, opt)
35
35
  name = ResolveKindName.(kind, opt)
36
36
 
37
- @name = KIND.of!(::String, name)
37
+ @name = STRICT.kind_of(::String, name)
38
38
  @kind = KIND.respond_to!(:===, kind)
39
39
  end
40
40
 
@@ -5,7 +5,7 @@ module Kind
5
5
  include Kind::BasicObject
6
6
 
7
7
  def self.[](*args)
8
- args.each { |arg| KIND.of!(::Symbol, arg) }
8
+ args.each { |arg| STRICT.kind_of(::Symbol, arg) }
9
9
 
10
10
  new(args)
11
11
  end
data/lib/kind/presence.rb CHANGED
@@ -7,7 +7,7 @@ module Kind
7
7
  extend self
8
8
 
9
9
  def call(object)
10
- return if KIND.null?(object)
10
+ return if KIND.nil_or_undefined?(object)
11
11
 
12
12
  return object.blank? ? nil : object if object.respond_to?(:blank?)
13
13
 
@@ -14,10 +14,12 @@ module Kind
14
14
  UNDEFINED != default ? default : block.call
15
15
  end
16
16
 
17
- def map(&_)
17
+ def map(_ = UNDEFINED, &_fn)
18
18
  self
19
19
  end
20
20
 
21
+ alias_method :|, :map
22
+ alias_method :>>, :map
21
23
  alias_method :map!, :map
22
24
  alias_method :then, :map
23
25
  alias_method :then!, :map
@@ -4,18 +4,21 @@ module Kind
4
4
  class Result::Monad
5
5
  include Result::Abstract
6
6
 
7
+ require 'kind/empty'
7
8
  require 'kind/result/monad/wrapper'
8
9
 
9
10
  attr_reader :type, :value
10
11
 
11
- def self.[](arg1 = UNDEFINED, arg2 = UNDEFINED, value_must_be_a: nil) # :nodoc:
12
- type = UNDEFINED == arg2 ? self::DEFAULT_TYPE : KIND.of!(::Symbol, arg1)
12
+ def self.[](arg1 = UNDEFINED, arg2 = UNDEFINED, opt = Empty::HASH) # :nodoc:
13
+ value_must_be_a = opt[:value_must_be_a]
14
+
15
+ type = UNDEFINED == arg2 ? self::DEFAULT_TYPE : STRICT.kind_of(::Symbol, arg1)
13
16
 
14
17
  Error.wrong_number_of_args!(given: 0, expected: '1 or 2') if UNDEFINED == arg1
15
18
 
16
19
  value = UNDEFINED == arg2 ? arg1 : arg2
17
20
 
18
- new(type, (value_must_be_a ? KIND.of!(value_must_be_a, value) : value))
21
+ new(type, (value_must_be_a ? STRICT.kind_of(value_must_be_a, value) : value))
19
22
  end
20
23
 
21
24
  private_class_method :new
@@ -29,10 +32,12 @@ module Kind
29
32
  raise NotImplementedError
30
33
  end
31
34
 
32
- def map(&_)
35
+ def map(_ = UNDEFINED, &_fn)
33
36
  raise NotImplementedError
34
37
  end
35
38
 
39
+ alias_method :|, :map
40
+ alias_method :>>, :map
36
41
  alias_method :map!, :map
37
42
  alias_method :then, :map
38
43
  alias_method :then!, :map
@@ -12,29 +12,42 @@ module Kind
12
12
  @value
13
13
  end
14
14
 
15
- def map(&fn)
16
- map!(&fn)
15
+ def map(callable = UNDEFINED, &fn)
16
+ _resolve_map(callable, fn)
17
17
  rescue Kind::Monad::Error => e
18
18
  raise e
19
19
  rescue StandardError => e
20
20
  Result::Failure[:exception, e]
21
21
  end
22
22
 
23
- def map!(&fn)
24
- monad = fn.call(@value)
25
-
26
- return monad if Result::Monad === monad
23
+ alias_method :then, :map
24
+ alias_method :and_then, :map
27
25
 
28
- raise Kind::Monad::Error.new('Kind::Success | Kind::Failure', monad)
26
+ def map!(callable = UNDEFINED, &fn)
27
+ _resolve_map(callable, fn)
29
28
  end
30
29
 
31
- alias_method :then, :map
30
+ alias_method :|, :map!
31
+ alias_method :>>, :map!
32
32
  alias_method :then!, :map!
33
- alias_method :and_then, :map
34
33
  alias_method :and_then!, :map!
35
34
 
36
35
  def inspect
37
36
  '#<%s type=%p value=%p>' % ['Kind::Success', type, value]
38
37
  end
38
+
39
+ private
40
+
41
+ def _resolve_map(callable, fn)
42
+ callable.respond_to?(:call) ? _map(callable) : _map(fn)
43
+ end
44
+
45
+ def _map(fn)
46
+ monad = fn.call(@value)
47
+
48
+ return monad if Result::Monad === monad
49
+
50
+ raise Kind::Monad::Error.new('Kind::Success | Kind::Failure', monad)
51
+ end
39
52
  end
40
53
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ module STRICT
5
+ [
6
+ :object_is_a, :class!, :kind_of,
7
+ :module_or_class, :module!, :not_nil
8
+ ].each { |method_name| remove_method(method_name) }
9
+
10
+ def object_is_a(_kind, value, _label = nil) # :nodoc:
11
+ value
12
+ end
13
+
14
+ def class!(value) # :nodoc:
15
+ value
16
+ end
17
+
18
+ def kind_of(_kind, value, _kind_name = nil) # :nodoc:
19
+ value
20
+ end
21
+
22
+ def module_or_class(value) # :nodoc:
23
+ value
24
+ end
25
+
26
+ def module!(value) # :nodoc:
27
+ value
28
+ end
29
+
30
+ def not_nil(value, label) # :nodoc:
31
+ value
32
+ end
33
+ end
34
+ end
data/lib/kind/try.rb CHANGED
@@ -9,7 +9,7 @@ module Kind
9
9
  extend self
10
10
 
11
11
  def call!(object, method_name, args = Empty::ARRAY) # :nodoc
12
- return if KIND.null?(object)
12
+ return if KIND.nil_or_undefined?(object)
13
13
 
14
14
  resolve(object, method_name, args)
15
15
  end
@@ -21,7 +21,7 @@ module Kind
21
21
 
22
22
  return result unless block_given?
23
23
 
24
- yield(result) unless KIND.null?(result)
24
+ yield(result) unless KIND.nil_or_undefined?(result)
25
25
  end
26
26
 
27
27
  def presence(*args, &block)
@@ -101,7 +101,7 @@ class KindValidator < ActiveModel::EachValidator
101
101
  def kind_is_not(expected, value)
102
102
  case expected
103
103
  when ::Class
104
- return if expected == Kind.of!(::Class, value) || value < expected
104
+ return if expected == Kind.of_class(value) || value < expected
105
105
 
106
106
  "must be the class or a subclass of `#{expected.name}`"
107
107
  when ::Module
data/lib/kind/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '5.2.0'
4
+ VERSION = '5.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kind
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0
4
+ version: 5.3.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: 2021-03-18 00:00:00.000000000 Z
11
+ date: 2021-03-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple type system (at runtime) for Ruby - free of dependencies.
14
14
  email:
@@ -31,8 +31,11 @@ files:
31
31
  - bin/setup
32
32
  - kind.gemspec
33
33
  - lib/kind.rb
34
+ - lib/kind/__lib__/action_steps.rb
34
35
  - lib/kind/__lib__/attributes.rb
35
36
  - lib/kind/__lib__/kind.rb
37
+ - lib/kind/__lib__/of.rb
38
+ - lib/kind/__lib__/strict.rb
36
39
  - lib/kind/__lib__/undefined.rb
37
40
  - lib/kind/action.rb
38
41
  - lib/kind/active_model/validation.rb
@@ -109,6 +112,7 @@ files:
109
112
  - lib/kind/result/monad.rb
110
113
  - lib/kind/result/monad/wrapper.rb
111
114
  - lib/kind/result/success.rb
115
+ - lib/kind/strict/disabled.rb
112
116
  - lib/kind/try.rb
113
117
  - lib/kind/validator.rb
114
118
  - lib/kind/version.rb