kind 5.0.0 → 5.1.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.sh +6 -1
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +38 -24
  5. data/Gemfile +13 -6
  6. data/README.md +11 -6
  7. data/kind.gemspec +1 -1
  8. data/lib/kind.rb +3 -14
  9. data/lib/kind/active_model/validation.rb +3 -4
  10. data/lib/kind/core.rb +13 -6
  11. data/lib/kind/{dig.rb → core/dig.rb} +0 -0
  12. data/lib/kind/{empty.rb → core/empty.rb} +0 -0
  13. data/lib/kind/{empty → core/empty}/constant.rb +0 -0
  14. data/lib/kind/{error.rb → core/error.rb} +0 -0
  15. data/lib/kind/{maybe.rb → core/maybe.rb} +6 -8
  16. data/lib/kind/{maybe → core/maybe}/none.rb +2 -2
  17. data/lib/kind/{maybe → core/maybe}/result.rb +0 -0
  18. data/lib/kind/{maybe → core/maybe}/some.rb +1 -1
  19. data/lib/kind/{maybe → core/maybe}/typed.rb +0 -0
  20. data/lib/kind/{maybe → core/maybe}/wrappable.rb +0 -0
  21. data/lib/kind/{presence.rb → core/presence.rb} +0 -0
  22. data/lib/kind/{try.rb → core/try.rb} +0 -0
  23. data/lib/kind/{type_checker.rb → core/type_checker.rb} +1 -1
  24. data/lib/kind/core/type_checkers.rb +30 -0
  25. data/lib/kind/{type_checkers → core/type_checkers}/custom/boolean.rb +0 -0
  26. data/lib/kind/{type_checkers → core/type_checkers}/custom/callable.rb +0 -0
  27. data/lib/kind/{type_checkers → core/type_checkers}/custom/lambda.rb +0 -0
  28. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/array.rb +0 -0
  29. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/class.rb +0 -0
  30. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/comparable.rb +0 -0
  31. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/enumerable.rb +0 -0
  32. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/enumerator.rb +0 -0
  33. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/file.rb +0 -0
  34. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/float.rb +0 -0
  35. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/hash.rb +0 -0
  36. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/integer.rb +0 -0
  37. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/io.rb +0 -0
  38. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/method.rb +0 -0
  39. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/module.rb +0 -0
  40. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/numeric.rb +0 -0
  41. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/proc.rb +0 -0
  42. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/queue.rb +0 -0
  43. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/range.rb +0 -0
  44. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/regexp.rb +0 -0
  45. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/string.rb +0 -0
  46. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/struct.rb +0 -0
  47. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/symbol.rb +0 -0
  48. data/lib/kind/{type_checkers/core → core/type_checkers/ruby}/time.rb +0 -0
  49. data/lib/kind/{type_checkers → core/type_checkers}/stdlib/open_struct.rb +0 -0
  50. data/lib/kind/{type_checkers → core/type_checkers}/stdlib/set.rb +0 -0
  51. data/lib/kind/core/undefined.rb +25 -3
  52. data/lib/kind/core/{kind.rb → utils/kind.rb} +0 -0
  53. data/lib/kind/core/utils/undefined.rb +7 -0
  54. data/lib/kind/validator.rb +107 -0
  55. data/lib/kind/version.rb +1 -1
  56. metadata +45 -46
  57. data/lib/kind/active_model/kind_validator.rb +0 -103
  58. data/lib/kind/type_checkers.rb +0 -30
  59. data/lib/kind/undefined.rb +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a58bdad80758ce4b68dd663984a2b505dc5bcc346861c8aa0da7826e458d71b
4
- data.tar.gz: 4de72ab2b437c0743e28440ddf7a637a03ee290d03d484157202f2d967b4863c
3
+ metadata.gz: 0115f034c70fde8d181ffb42e0d2fddb0bb7376e84120d8f7017ce9708ccab53
4
+ data.tar.gz: 1e24f96749ad14ce29bf86314423be332a7a424ff9c562e7451d2ab0d08a7fef
5
5
  SHA512:
6
- metadata.gz: 8ab61cb4339b6e979e505cf623b391ce9b946b853893b7e32ea734b6ff325ca007b8509b4c66669a90cfbdade64830843ed7ac0a2aeb30eb4324dca11d056c79
7
- data.tar.gz: 04cc0c6f36ab19167de1b13cd484ccd00b576c13f1703ec42017c334e5c270b02e9d77d20f14346b74d2564837cf97024cc3bafc0dd7b7675c4ac8c0b42c5398
6
+ metadata.gz: 675a83c3e389538b39d75772b55b5f0ce179b2bedd3234ee973865312aa9bbe8e681350412597bca0ce3e7842878f27004139b88c2b8489c0c27f4d1cd6238fd
7
+ data.tar.gz: 03d5592c9bd8eaa9591aa7b914feae2ab60678ead26aba64f7f175c673e26a584c2d3fd32bec20fb868c28e101f96e0a2bcf5e14effb15148cb905b4ca8b548d
data/.travis.sh CHANGED
@@ -19,12 +19,17 @@ function run_with_am_version_and_bundler {
19
19
  run_with_bundler "$2" "ACTIVEMODEL_VERSION=$1"
20
20
  }
21
21
 
22
+ if [[ $RUBY_V =~ "ruby 2.[12]." ]]; then
23
+ run_with_bundler "$BUNDLER_V1"
24
+
25
+ run_with_am_version_and_bundler "3.2" "$BUNDLER_V1"
26
+ fi
27
+
22
28
  RUBY_2_2345="ruby 2.[2345]."
23
29
 
24
30
  if [[ $RUBY_V =~ $RUBY_2_2345 ]]; then
25
31
  run_with_bundler "$BUNDLER_V1"
26
32
 
27
- run_with_am_version_and_bundler "3.2" "$BUNDLER_V1"
28
33
  run_with_am_version_and_bundler "4.0" "$BUNDLER_V1"
29
34
  run_with_am_version_and_bundler "4.1" "$BUNDLER_V1"
30
35
  run_with_am_version_and_bundler "4.2" "$BUNDLER_V1"
data/.travis.yml CHANGED
@@ -7,6 +7,7 @@ cache:
7
7
  - /home/travis/.rvm/
8
8
 
9
9
  rvm:
10
+ - 2.1.10
10
11
  - 2.2.2
11
12
  - 2.3.0
12
13
  - 2.4.0
data/CHANGELOG.md CHANGED
@@ -3,66 +3,69 @@
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.1.0 (2021-02-23)](#510-2021-02-23)
7
+ - [Added](#added)
8
+ - [Deprecated](#deprecated)
6
9
  - [5.0.0 (2021-02-22)](#500-2021-02-22)
7
10
  - [Breaking Changes](#breaking-changes)
8
11
  - [Removed](#removed)
9
12
  - [4.1.0 (2021-02-22)](#410-2021-02-22)
10
- - [Added](#added)
11
- - [4.0.0 (2021-02-22)](#400-2021-02-22)
12
13
  - [Added](#added-1)
13
- - [Deprecated](#deprecated)
14
+ - [4.0.0 (2021-02-22)](#400-2021-02-22)
15
+ - [Added](#added-2)
16
+ - [Deprecated](#deprecated-1)
14
17
  - [Fixed](#fixed)
15
18
  - [3.1.0 (2020-07-08)](#310-2020-07-08)
16
- - [Added](#added-2)
19
+ - [Added](#added-3)
17
20
  - [3.0.0 (2020-06-25)](#300-2020-06-25)
18
21
  - [Breaking Changes](#breaking-changes-1)
19
- - [Added](#added-3)
20
- - [2.3.0 (2020-06-24)](#230-2020-06-24)
21
22
  - [Added](#added-4)
22
- - [2.2.0 (2020-06-23)](#220-2020-06-23)
23
+ - [2.3.0 (2020-06-24)](#230-2020-06-24)
23
24
  - [Added](#added-5)
24
- - [2.1.0 (2020-05-12)](#210-2020-05-12)
25
+ - [2.2.0 (2020-06-23)](#220-2020-06-23)
25
26
  - [Added](#added-6)
27
+ - [2.1.0 (2020-05-12)](#210-2020-05-12)
28
+ - [Added](#added-7)
26
29
  - [Breaking Changes](#breaking-changes-2)
27
30
  - [2.0.0 (2020-05-07)](#200-2020-05-07)
28
- - [Added](#added-7)
31
+ - [Added](#added-8)
29
32
  - [Breaking Changes](#breaking-changes-3)
30
33
  - [Removed](#removed-1)
31
34
  - [1.9.0 (2020-05-06)](#190-2020-05-06)
32
- - [Added](#added-8)
33
- - [1.8.0 (2020-05-03)](#180-2020-05-03)
34
35
  - [Added](#added-9)
36
+ - [1.8.0 (2020-05-03)](#180-2020-05-03)
37
+ - [Added](#added-10)
35
38
  - [1.7.0 (2020-05-03)](#170-2020-05-03)
36
39
  - [Fixed](#fixed-1)
37
40
  - [1.6.0 (2020-04-17)](#160-2020-04-17)
38
- - [Added](#added-10)
41
+ - [Added](#added-11)
39
42
  - [Changes](#changes)
40
43
  - [1.5.0 (2020-04-12)](#150-2020-04-12)
41
- - [Added](#added-11)
42
- - [1.4.0 (2020-04-12)](#140-2020-04-12)
43
44
  - [Added](#added-12)
44
- - [1.3.0 (2020-04-12)](#130-2020-04-12)
45
+ - [1.4.0 (2020-04-12)](#140-2020-04-12)
45
46
  - [Added](#added-13)
46
- - [1.2.0 (2020-04-12)](#120-2020-04-12)
47
+ - [1.3.0 (2020-04-12)](#130-2020-04-12)
47
48
  - [Added](#added-14)
48
- - [1.1.0 (2020-04-09)](#110-2020-04-09)
49
+ - [1.2.0 (2020-04-12)](#120-2020-04-12)
49
50
  - [Added](#added-15)
51
+ - [1.1.0 (2020-04-09)](#110-2020-04-09)
52
+ - [Added](#added-16)
50
53
  - [Fixed](#fixed-2)
51
54
  - [1.0.0 (2020-03-16)](#100-2020-03-16)
52
- - [Added](#added-16)
53
- - [0.6.0 (2020-01-06)](#060-2020-01-06)
54
55
  - [Added](#added-17)
55
- - [0.5.0 (2020-01-04)](#050-2020-01-04)
56
+ - [0.6.0 (2020-01-06)](#060-2020-01-06)
56
57
  - [Added](#added-18)
57
- - [0.4.0 (2020-01-03)](#040-2020-01-03)
58
+ - [0.5.0 (2020-01-04)](#050-2020-01-04)
58
59
  - [Added](#added-19)
59
- - [0.3.0 (2020-01-03)](#030-2020-01-03)
60
+ - [0.4.0 (2020-01-03)](#040-2020-01-03)
60
61
  - [Added](#added-20)
62
+ - [0.3.0 (2020-01-03)](#030-2020-01-03)
63
+ - [Added](#added-21)
61
64
  - [Breaking Changes](#breaking-changes-4)
62
65
  - [0.2.0 (2020-01-02)](#020-2020-01-02)
63
- - [Added](#added-21)
64
- - [0.1.0 (2019-12-26)](#010-2019-12-26)
65
66
  - [Added](#added-22)
67
+ - [0.1.0 (2019-12-26)](#010-2019-12-26)
68
+ - [Added](#added-23)
66
69
 
67
70
  ## Unreleased
68
71
 
@@ -74,6 +77,17 @@ This project follows [semver 2.0.0](http://semver.org/spec/v2.0.0.html) and the
74
77
  ### Fixed
75
78
  -->
76
79
 
80
+ 5.1.0 (2021-02-23)
81
+ ------------------
82
+
83
+ ### Added
84
+
85
+ * [#45](https://github.com/serradura/kind/pull/45) - Add support to Ruby `>= 2.1.0`.
86
+
87
+ ### Deprecated
88
+
89
+ * [#45](https://github.com/serradura/kind/pull/45) - `kind/active_model/validation` is deprecated; use `kind/validator` instead.
90
+
77
91
  5.0.0 (2021-02-22)
78
92
  ------------------
79
93
 
data/Gemfile CHANGED
@@ -18,24 +18,31 @@ activemodel = case activemodel_version
18
18
 
19
19
  simplecov_version =
20
20
  case RUBY_VERSION
21
- when /\A2.[23]/ then '0.17.1'
21
+ when /\A2.[123]/ then '0.17.1'
22
22
  when /\A2.4/ then '~> 0.18.5'
23
23
  else '~> 0.19'
24
24
  end
25
25
 
26
+ is_ruby_2_1 = RUBY_VERSION <= '2.2.0'
27
+
28
+ minitest_version =
29
+ if activemodel_version
30
+ activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
31
+ else
32
+ is_ruby_2_1 ? '~> 4.2' : '~> 5.0'
33
+ end
34
+
26
35
  group :test do
27
36
  if activemodel_version
28
37
  gem 'activesupport', activemodel, require: false
29
- gem 'activemodel', activemodel, require: false
30
- gem 'minitest', activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
31
- else
32
- gem 'minitest', '~> 5.0'
38
+ gem 'activemodel' , activemodel, require: false
33
39
  end
34
40
 
41
+ gem 'minitest' , minitest_version
35
42
  gem 'simplecov', simplecov_version, require: false
36
43
  end
37
44
 
38
- gem 'rake', '~> 13.0'
45
+ gem 'rake', is_ruby_2_1 ? '~> 12.3' : '~> 13.0'
39
46
 
40
47
  # Specify your gem's dependencies in type_validator.gemspec
41
48
  gemspec
data/README.md CHANGED
@@ -5,12 +5,16 @@
5
5
  </p>
6
6
 
7
7
  <p align="center">
8
- <img src="https://img.shields.io/badge/ruby->%3D%202.2.0-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
9
-
10
8
  <a href="https://rubygems.org/gems/kind">
11
9
  <img alt="Gem" src="https://img.shields.io/gem/v/kind.svg?style=flat-square">
12
10
  </a>
13
11
 
12
+ <img src="https://img.shields.io/badge/ruby%20%3E=%202.1.0,%20%3C%203.1-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
13
+
14
+ <img src="https://img.shields.io/badge/rails%20%3E=%203.2.0,%20%3C%207-rails.svg?colorA=8B0000&colorB=FF0000" alt="Rails">
15
+
16
+ <br />
17
+
14
18
  <a href="https://travis-ci.com/serradura/kind">
15
19
  <img alt="Build Status" src="https://travis-ci.com/serradura/kind.svg?branch=master">
16
20
  </a>
@@ -35,7 +39,7 @@ One of the goals of this project is to do simple type checking like `"some strin
35
39
  Version | Documentation
36
40
  ---------- | -------------
37
41
  unreleased | https://github.com/serradura/u-case/blob/main/README.md
38
- 5.0.0 | https://github.com/serradura/u-case/blob/v5.x/README.md
42
+ 5.1.0 | https://github.com/serradura/u-case/blob/v5.x/README.md
39
43
  4.1.0 | https://github.com/serradura/u-case/blob/v4.x/README.md
40
44
  3.1.0 | https://github.com/serradura/u-case/blob/v3.x/README.md
41
45
  2.3.0 | https://github.com/serradura/u-case/blob/v2.x/README.md
@@ -117,7 +121,8 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
117
121
 
118
122
  | u-case | branch | ruby | activemodel |
119
123
  | -------------- | ------- | -------- | -------------- |
120
- | unreleased | main | >= 2.2.0 | >= 3.2, <= 6.1 |
124
+ | unreleased | main | >= 2.1.0 | >= 3.2, <= 6.1 |
125
+ | 5.1.0 | v5.x | >= 2.1.0 | >= 3.2, <= 6.1 |
121
126
  | 4.1.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
122
127
  | 3.1.0 | v3.x | >= 2.2.0 | >= 3.2, <= 6.1 |
123
128
  | 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
@@ -1470,10 +1475,10 @@ And to make use of it, you will need to do an explicitly require. e.g:
1470
1475
 
1471
1476
  ```ruby
1472
1477
  # In some Gemfile
1473
- gem 'kind', require: 'kind/active_model/validation'
1478
+ gem 'kind', require: 'kind/validator'
1474
1479
 
1475
1480
  # In some .rb file
1476
- require 'kind/active_model/validation'
1481
+ require 'kind/validator'
1477
1482
  ```
1478
1483
 
1479
1484
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
data/kind.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.description = %q{A simple type system (at runtime) for Ruby - free of dependencies.}
11
11
  spec.homepage = 'https://github.com/serradura/kind'
12
12
  spec.license = 'MIT'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.2.0')
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.1.0')
14
14
 
15
15
  spec.metadata['homepage_uri'] = spec.homepage
16
16
  spec.metadata['source_code_uri'] = 'https://github.com/serradura/kind'
data/lib/kind.rb CHANGED
@@ -3,21 +3,10 @@
3
3
  require 'set'
4
4
  require 'ostruct'
5
5
 
6
- require 'kind/version'
7
- require 'kind/core'
8
-
9
- require 'kind/error'
10
- require 'kind/empty'
11
- require 'kind/dig'
12
- require 'kind/try'
13
- require 'kind/presence'
14
- require 'kind/undefined'
15
- require 'kind/maybe'
16
-
17
- require 'kind/type_checker'
18
- require 'kind/type_checkers'
19
-
20
6
  module Kind
7
+ require 'kind/version'
8
+ require 'kind/core'
9
+
21
10
  extend self
22
11
 
23
12
  def is?(kind, arg)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kind'
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/core.rb CHANGED
@@ -1,8 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Kind
4
- module Core
5
- require 'kind/core/kind'
6
- require 'kind/core/undefined'
7
- end
8
- end
3
+ require 'kind/core/utils/kind'
4
+ require 'kind/core/utils/undefined'
5
+
6
+ require 'kind/core/error'
7
+ require 'kind/core/empty'
8
+ require 'kind/core/dig'
9
+ require 'kind/core/try'
10
+ require 'kind/core/presence'
11
+ require 'kind/core/undefined'
12
+ require 'kind/core/maybe'
13
+
14
+ require 'kind/core/type_checker'
15
+ require 'kind/core/type_checkers'
File without changes
File without changes
File without changes
File without changes
@@ -1,16 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'kind/dig'
4
-
5
3
  module Kind
6
4
  module Maybe
7
- extend self
5
+ require 'kind/core/maybe/result'
6
+ require 'kind/core/maybe/none'
7
+ require 'kind/core/maybe/some'
8
+ require 'kind/core/maybe/wrappable'
9
+ require 'kind/core/maybe/typed'
8
10
 
9
- require 'kind/maybe/result'
10
- require 'kind/maybe/none'
11
- require 'kind/maybe/some'
12
- require 'kind/maybe/wrappable'
13
- require 'kind/maybe/typed'
11
+ extend self
14
12
 
15
13
  def new(value)
16
14
  (KIND.null?(value) ? None : Some)
@@ -44,11 +44,11 @@ module Kind
44
44
  NONE_WITH_NIL_VALUE = None.new(nil)
45
45
  NONE_WITH_UNDEFINED_VALUE = None.new(Undefined)
46
46
 
47
- def none
47
+ def self.none
48
48
  NONE_WITH_NIL_VALUE
49
49
  end
50
50
 
51
- def __none__(value) # :nodoc:
51
+ def self.__none__(value) # :nodoc:
52
52
  None.new(value)
53
53
  end
54
54
 
File without changes
@@ -79,7 +79,7 @@ module Kind
79
79
 
80
80
  VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
81
81
 
82
- def some(value)
82
+ def self.some(value)
83
83
  return Maybe::Some.new(value) if !KIND.null?(value)
84
84
 
85
85
  raise ArgumentError, VALUE_CANT_BE_NONE
File without changes
File without changes
File without changes
File without changes
@@ -33,7 +33,7 @@ module Kind
33
33
  def value?(value = UNDEFINED)
34
34
  return self === value if UNDEFINED != value
35
35
 
36
- @__is_value ||= ->(ck) { ->(value) { ck === value } }.(self)
36
+ @__is_value ||= ->(tc) { ->(arg) { tc === arg } }.(self)
37
37
  end
38
38
 
39
39
  def value(arg, default:)
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kind/core/type_checkers/ruby/array'
4
+ require 'kind/core/type_checkers/ruby/class'
5
+ require 'kind/core/type_checkers/ruby/comparable'
6
+ require 'kind/core/type_checkers/ruby/enumerable'
7
+ require 'kind/core/type_checkers/ruby/enumerator'
8
+ require 'kind/core/type_checkers/ruby/file'
9
+ require 'kind/core/type_checkers/ruby/float'
10
+ require 'kind/core/type_checkers/ruby/hash'
11
+ require 'kind/core/type_checkers/ruby/integer'
12
+ require 'kind/core/type_checkers/ruby/io'
13
+ require 'kind/core/type_checkers/ruby/module'
14
+ require 'kind/core/type_checkers/ruby/method'
15
+ require 'kind/core/type_checkers/ruby/numeric'
16
+ require 'kind/core/type_checkers/ruby/proc'
17
+ require 'kind/core/type_checkers/ruby/queue'
18
+ require 'kind/core/type_checkers/ruby/range'
19
+ require 'kind/core/type_checkers/ruby/regexp'
20
+ require 'kind/core/type_checkers/ruby/string'
21
+ require 'kind/core/type_checkers/ruby/struct'
22
+ require 'kind/core/type_checkers/ruby/symbol'
23
+ require 'kind/core/type_checkers/ruby/time'
24
+
25
+ require 'kind/core/type_checkers/stdlib/open_struct'
26
+ require 'kind/core/type_checkers/stdlib/set'
27
+
28
+ require 'kind/core/type_checkers/custom/boolean'
29
+ require 'kind/core/type_checkers/custom/callable'
30
+ require 'kind/core/type_checkers/custom/lambda'
@@ -1,7 +1,29 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Kind
4
- UNDEFINED = Object.new.freeze
3
+ Undefined = Object.new.tap do |undefined|
4
+ def undefined.inspect
5
+ @inspect ||= 'Kind::Undefined'.freeze
6
+ end
7
+
8
+ def undefined.to_s
9
+ inspect
10
+ end
11
+
12
+ def undefined.clone
13
+ self
14
+ end
15
+
16
+ def undefined.dup
17
+ clone
18
+ end
19
+
20
+ def undefined.default(value, default)
21
+ return value if self != value
22
+
23
+ default.respond_to?(:call) ? default.call : default
24
+ end
5
25
 
6
- private_constant :UNDEFINED
26
+ undefined.inspect
27
+ undefined.freeze
28
+ end
7
29
  end
File without changes
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ UNDEFINED = Object.new.freeze
5
+
6
+ private_constant :UNDEFINED
7
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'kind'
4
+
3
5
  module Kind
4
6
  module Validator
5
7
  DEFAULT_STRATEGIES = ::Set.new(%w[instance_of kind_of]).freeze
@@ -38,3 +40,108 @@ module Kind
38
40
  end
39
41
  end
40
42
  end
43
+
44
+ require 'active_model'
45
+ require 'active_model/validations'
46
+
47
+ class KindValidator < ActiveModel::EachValidator
48
+ def validate_each(record, attribute, value)
49
+ return if options[:allow_nil] && value.nil?
50
+
51
+ return unless error = call_validation_for(attribute, value)
52
+
53
+ raise Kind::Error.new("#{attribute} #{error}") if options[:strict]
54
+
55
+ record.errors.add(attribute, error)
56
+ end
57
+
58
+ private
59
+
60
+ def call_validation_for(attribute, value)
61
+ expected = options[:with] || options[:in]
62
+
63
+ return validate_with_default_strategy(expected, value) if expected
64
+
65
+ return kind_of(expected, value) if expected = options[:of]
66
+ return kind_is(expected, value) if expected = options[:is]
67
+ return respond_to(expected, value) if expected = options[:respond_to]
68
+ return instance_of(expected, value) if expected = options[:instance_of]
69
+ return array_with(expected, value) if expected = options[:array_with]
70
+ return array_of(expected, value) if expected = options[:array_of]
71
+
72
+ raise Kind::Validator::InvalidDefinition.new(attribute)
73
+ end
74
+
75
+ def validate_with_default_strategy(expected, value)
76
+ send(Kind::Validator.default_strategy, expected, value)
77
+ end
78
+
79
+ def kind_of(expected, value)
80
+ types = Array(expected)
81
+
82
+ return if types.any? { |type| type === value }
83
+
84
+ "must be a kind of: #{types.map { |type| type.name }.join(', ')}"
85
+ end
86
+
87
+ CLASS_OR_MODULE = 'Class/Module'.freeze
88
+
89
+ def kind_is(expected, value)
90
+ return kind_is_not(expected, value) unless expected.kind_of?(::Array)
91
+
92
+ result = expected.map { |kind| kind_is_not(kind, value) }.tap(&:compact!)
93
+
94
+ result.empty? || result.size < expected.size ? nil : result.join(', ')
95
+ end
96
+
97
+ def kind_is_not(expected, value)
98
+ case expected
99
+ when ::Class
100
+ return if expected == Kind::Class[value] || value < expected
101
+
102
+ "must be the class or a subclass of `#{expected.name}`"
103
+ when ::Module
104
+ return if value.kind_of?(Class) && value <= expected
105
+ return if expected == Kind.of_module_or_class(value) || value.kind_of?(expected)
106
+
107
+ "must include the `#{expected.name}` module"
108
+ else
109
+ raise Kind::Error.new(CLASS_OR_MODULE, expected)
110
+ end
111
+ end
112
+
113
+ def respond_to(expected, value)
114
+ method_names = Array(expected)
115
+
116
+ expected_methods = method_names.select { |method_name| !value.respond_to?(method_name) }
117
+ expected_methods.map! { |method_name| "`#{method_name}`" }
118
+
119
+ return if expected_methods.empty?
120
+
121
+ methods = expected_methods.size == 1 ? 'method' : 'methods'
122
+
123
+ "must respond to the #{methods}: #{expected_methods.join(', ')}"
124
+ end
125
+
126
+ def instance_of(expected, value)
127
+ types = Array(expected)
128
+
129
+ return if types.any? { |type| value.instance_of?(type) }
130
+
131
+ "must be an instance of: #{types.map { |klass| klass.name }.join(', ')}"
132
+ end
133
+
134
+ def array_with(expected, value)
135
+ return if value.kind_of?(::Array) && !value.empty? && (value - Kind::Array[expected]).empty?
136
+
137
+ "must be an array with: #{expected.join(', ')}"
138
+ end
139
+
140
+ def array_of(expected, value)
141
+ types = Array(expected)
142
+
143
+ return if value.kind_of?(::Array) && !value.empty? && value.all? { |val| types.any? { |type| type === val } }
144
+
145
+ "must be an array of: #{types.map { |klass| klass.name }.join(', ')}"
146
+ end
147
+ end
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.0.0'
4
+ VERSION = '5.1.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.0.0
4
+ version: 5.1.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-02-23 00:00:00.000000000 Z
11
+ date: 2021-02-24 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,52 +31,51 @@ files:
31
31
  - bin/setup
32
32
  - kind.gemspec
33
33
  - lib/kind.rb
34
- - lib/kind/active_model/kind_validator.rb
35
34
  - lib/kind/active_model/validation.rb
36
35
  - lib/kind/core.rb
37
- - lib/kind/core/kind.rb
36
+ - lib/kind/core/dig.rb
37
+ - lib/kind/core/empty.rb
38
+ - lib/kind/core/empty/constant.rb
39
+ - lib/kind/core/error.rb
40
+ - lib/kind/core/maybe.rb
41
+ - lib/kind/core/maybe/none.rb
42
+ - lib/kind/core/maybe/result.rb
43
+ - lib/kind/core/maybe/some.rb
44
+ - lib/kind/core/maybe/typed.rb
45
+ - lib/kind/core/maybe/wrappable.rb
46
+ - lib/kind/core/presence.rb
47
+ - lib/kind/core/try.rb
48
+ - lib/kind/core/type_checker.rb
49
+ - lib/kind/core/type_checkers.rb
50
+ - lib/kind/core/type_checkers/custom/boolean.rb
51
+ - lib/kind/core/type_checkers/custom/callable.rb
52
+ - lib/kind/core/type_checkers/custom/lambda.rb
53
+ - lib/kind/core/type_checkers/ruby/array.rb
54
+ - lib/kind/core/type_checkers/ruby/class.rb
55
+ - lib/kind/core/type_checkers/ruby/comparable.rb
56
+ - lib/kind/core/type_checkers/ruby/enumerable.rb
57
+ - lib/kind/core/type_checkers/ruby/enumerator.rb
58
+ - lib/kind/core/type_checkers/ruby/file.rb
59
+ - lib/kind/core/type_checkers/ruby/float.rb
60
+ - lib/kind/core/type_checkers/ruby/hash.rb
61
+ - lib/kind/core/type_checkers/ruby/integer.rb
62
+ - lib/kind/core/type_checkers/ruby/io.rb
63
+ - lib/kind/core/type_checkers/ruby/method.rb
64
+ - lib/kind/core/type_checkers/ruby/module.rb
65
+ - lib/kind/core/type_checkers/ruby/numeric.rb
66
+ - lib/kind/core/type_checkers/ruby/proc.rb
67
+ - lib/kind/core/type_checkers/ruby/queue.rb
68
+ - lib/kind/core/type_checkers/ruby/range.rb
69
+ - lib/kind/core/type_checkers/ruby/regexp.rb
70
+ - lib/kind/core/type_checkers/ruby/string.rb
71
+ - lib/kind/core/type_checkers/ruby/struct.rb
72
+ - lib/kind/core/type_checkers/ruby/symbol.rb
73
+ - lib/kind/core/type_checkers/ruby/time.rb
74
+ - lib/kind/core/type_checkers/stdlib/open_struct.rb
75
+ - lib/kind/core/type_checkers/stdlib/set.rb
38
76
  - lib/kind/core/undefined.rb
39
- - lib/kind/dig.rb
40
- - lib/kind/empty.rb
41
- - lib/kind/empty/constant.rb
42
- - lib/kind/error.rb
43
- - lib/kind/maybe.rb
44
- - lib/kind/maybe/none.rb
45
- - lib/kind/maybe/result.rb
46
- - lib/kind/maybe/some.rb
47
- - lib/kind/maybe/typed.rb
48
- - lib/kind/maybe/wrappable.rb
49
- - lib/kind/presence.rb
50
- - lib/kind/try.rb
51
- - lib/kind/type_checker.rb
52
- - lib/kind/type_checkers.rb
53
- - lib/kind/type_checkers/core/array.rb
54
- - lib/kind/type_checkers/core/class.rb
55
- - lib/kind/type_checkers/core/comparable.rb
56
- - lib/kind/type_checkers/core/enumerable.rb
57
- - lib/kind/type_checkers/core/enumerator.rb
58
- - lib/kind/type_checkers/core/file.rb
59
- - lib/kind/type_checkers/core/float.rb
60
- - lib/kind/type_checkers/core/hash.rb
61
- - lib/kind/type_checkers/core/integer.rb
62
- - lib/kind/type_checkers/core/io.rb
63
- - lib/kind/type_checkers/core/method.rb
64
- - lib/kind/type_checkers/core/module.rb
65
- - lib/kind/type_checkers/core/numeric.rb
66
- - lib/kind/type_checkers/core/proc.rb
67
- - lib/kind/type_checkers/core/queue.rb
68
- - lib/kind/type_checkers/core/range.rb
69
- - lib/kind/type_checkers/core/regexp.rb
70
- - lib/kind/type_checkers/core/string.rb
71
- - lib/kind/type_checkers/core/struct.rb
72
- - lib/kind/type_checkers/core/symbol.rb
73
- - lib/kind/type_checkers/core/time.rb
74
- - lib/kind/type_checkers/custom/boolean.rb
75
- - lib/kind/type_checkers/custom/callable.rb
76
- - lib/kind/type_checkers/custom/lambda.rb
77
- - lib/kind/type_checkers/stdlib/open_struct.rb
78
- - lib/kind/type_checkers/stdlib/set.rb
79
- - lib/kind/undefined.rb
77
+ - lib/kind/core/utils/kind.rb
78
+ - lib/kind/core/utils/undefined.rb
80
79
  - lib/kind/validator.rb
81
80
  - lib/kind/version.rb
82
81
  - test.sh
@@ -94,7 +93,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
93
  requirements:
95
94
  - - ">="
96
95
  - !ruby/object:Gem::Version
97
- version: 2.2.0
96
+ version: 2.1.0
98
97
  required_rubygems_version: !ruby/object:Gem::Requirement
99
98
  requirements:
100
99
  - - ">="
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class KindValidator < ActiveModel::EachValidator
4
- def validate_each(record, attribute, value)
5
- return if options[:allow_nil] && value.nil?
6
-
7
- return unless error = call_validation_for(attribute, value)
8
-
9
- raise Kind::Error.new("#{attribute} #{error}") if options[:strict]
10
-
11
- record.errors.add(attribute, error)
12
- end
13
-
14
- private
15
-
16
- def call_validation_for(attribute, value)
17
- expected = options[:with] || options[:in]
18
-
19
- return validate_with_default_strategy(expected, value) if expected
20
-
21
- return kind_of(expected, value) if expected = options[:of]
22
- return kind_is(expected, value) if expected = options[:is]
23
- return respond_to(expected, value) if expected = options[:respond_to]
24
- return instance_of(expected, value) if expected = options[:instance_of]
25
- return array_with(expected, value) if expected = options[:array_with]
26
- return array_of(expected, value) if expected = options[:array_of]
27
-
28
- raise Kind::Validator::InvalidDefinition.new(attribute)
29
- end
30
-
31
- def validate_with_default_strategy(expected, value)
32
- send(Kind::Validator.default_strategy, expected, value)
33
- end
34
-
35
- def kind_of(expected, value)
36
- types = Array(expected)
37
-
38
- return if types.any? { |type| type === value }
39
-
40
- "must be a kind of: #{types.map { |type| type.name }.join(', ')}"
41
- end
42
-
43
- CLASS_OR_MODULE = 'Class/Module'.freeze
44
-
45
- def kind_is(expected, value)
46
- return kind_is_not(expected, value) unless expected.kind_of?(::Array)
47
-
48
- result = expected.map { |kind| kind_is_not(kind, value) }.tap(&:compact!)
49
-
50
- result.empty? || result.size < expected.size ? nil : result.join(', ')
51
- end
52
-
53
- def kind_is_not(expected, value)
54
- case expected
55
- when ::Class
56
- return if expected == Kind::Class[value] || value < expected
57
-
58
- "must be the class or a subclass of `#{expected.name}`"
59
- when ::Module
60
- return if value.kind_of?(Class) && value <= expected
61
- return if expected == Kind.of_module_or_class(value) || value.kind_of?(expected)
62
-
63
- "must include the `#{expected.name}` module"
64
- else
65
- raise Kind::Error.new(CLASS_OR_MODULE, expected)
66
- end
67
- end
68
-
69
- def respond_to(expected, value)
70
- method_names = Array(expected)
71
-
72
- expected_methods = method_names.select { |method_name| !value.respond_to?(method_name) }
73
- expected_methods.map! { |method_name| "`#{method_name}`" }
74
-
75
- return if expected_methods.empty?
76
-
77
- methods = expected_methods.size == 1 ? 'method' : 'methods'
78
-
79
- "must respond to the #{methods}: #{expected_methods.join(', ')}"
80
- end
81
-
82
- def instance_of(expected, value)
83
- types = Array(expected)
84
-
85
- return if types.any? { |type| value.instance_of?(type) }
86
-
87
- "must be an instance of: #{types.map { |klass| klass.name }.join(', ')}"
88
- end
89
-
90
- def array_with(expected, value)
91
- return if value.kind_of?(::Array) && !value.empty? && (value - Kind::Array[expected]).empty?
92
-
93
- "must be an array with: #{expected.join(', ')}"
94
- end
95
-
96
- def array_of(expected, value)
97
- types = Array(expected)
98
-
99
- return if value.kind_of?(::Array) && !value.empty? && value.all? { |value| types.any? { |type| value.kind_of?(type) } }
100
-
101
- "must be an array of: #{types.map { |klass| klass.name }.join(', ')}"
102
- end
103
- end
@@ -1,30 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'kind/type_checkers/core/array'
4
- require 'kind/type_checkers/core/class'
5
- require 'kind/type_checkers/core/comparable'
6
- require 'kind/type_checkers/core/enumerable'
7
- require 'kind/type_checkers/core/enumerator'
8
- require 'kind/type_checkers/core/file'
9
- require 'kind/type_checkers/core/float'
10
- require 'kind/type_checkers/core/hash'
11
- require 'kind/type_checkers/core/integer'
12
- require 'kind/type_checkers/core/io'
13
- require 'kind/type_checkers/core/module'
14
- require 'kind/type_checkers/core/method'
15
- require 'kind/type_checkers/core/numeric'
16
- require 'kind/type_checkers/core/proc'
17
- require 'kind/type_checkers/core/queue'
18
- require 'kind/type_checkers/core/range'
19
- require 'kind/type_checkers/core/regexp'
20
- require 'kind/type_checkers/core/string'
21
- require 'kind/type_checkers/core/struct'
22
- require 'kind/type_checkers/core/symbol'
23
- require 'kind/type_checkers/core/time'
24
-
25
- require 'kind/type_checkers/stdlib/open_struct'
26
- require 'kind/type_checkers/stdlib/set'
27
-
28
- require 'kind/type_checkers/custom/boolean'
29
- require 'kind/type_checkers/custom/callable'
30
- require 'kind/type_checkers/custom/lambda'
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
- module Kind
3
- Undefined = Object.new.tap do |undefined|
4
- def undefined.inspect
5
- @inspect ||= 'Kind::Undefined'.freeze
6
- end
7
-
8
- def undefined.to_s
9
- inspect
10
- end
11
-
12
- def undefined.clone
13
- self
14
- end
15
-
16
- def undefined.dup
17
- clone
18
- end
19
-
20
- def undefined.default(value, default)
21
- return value if self != value
22
-
23
- default.respond_to?(:call) ? default.call : default
24
- end
25
-
26
- undefined.inspect
27
- undefined.freeze
28
- end
29
- end