kind 5.0.0 → 5.1.0

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