kind 5.2.0 → 5.3.0

Sign up to get free protection for your applications and to get access to all the features.
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