smart_types 0.1.0.alpha3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -1
- data/.travis.yml +6 -5
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +74 -48
- data/README.md +292 -22
- data/Rakefile +1 -1
- data/bin/console +2 -2
- data/lib/smart_core/types/errors.rb +4 -0
- data/lib/smart_core/types/primitive.rb +67 -20
- data/lib/smart_core/types/primitive/factory.rb +48 -8
- data/lib/smart_core/types/primitive/factory/definition_context.rb +116 -6
- data/lib/smart_core/types/primitive/invariant_control.rb +64 -0
- data/lib/smart_core/types/primitive/invariant_control/chain.rb +58 -0
- data/lib/smart_core/types/primitive/invariant_control/chain/result.rb +64 -0
- data/lib/smart_core/types/primitive/invariant_control/factory.rb +54 -0
- data/lib/smart_core/types/primitive/invariant_control/factory/chain_definition_context.rb +39 -0
- data/lib/smart_core/types/primitive/invariant_control/result.rb +104 -0
- data/lib/smart_core/types/primitive/invariant_control/single.rb +54 -0
- data/lib/smart_core/types/primitive/invariant_control/single/result.rb +63 -0
- data/lib/smart_core/types/primitive/mult_factory.rb +25 -10
- data/lib/smart_core/types/primitive/mult_factory/definition_context.rb +5 -3
- data/lib/smart_core/types/primitive/mult_validator.rb +34 -0
- data/lib/smart_core/types/primitive/mult_validator/result.rb +8 -0
- data/lib/smart_core/types/primitive/nilable_factory.rb +24 -9
- data/lib/smart_core/types/primitive/nilable_validator.rb +83 -0
- data/lib/smart_core/types/primitive/nilable_validator/result.rb +78 -0
- data/lib/smart_core/types/primitive/sum_factory.rb +25 -10
- data/lib/smart_core/types/primitive/sum_factory/definition_context.rb +4 -2
- data/lib/smart_core/types/primitive/sum_validator.rb +101 -0
- data/lib/smart_core/types/primitive/sum_validator/result.rb +100 -0
- data/lib/smart_core/types/primitive/undefined_caster.rb +3 -4
- data/lib/smart_core/types/primitive/validator.rb +84 -0
- data/lib/smart_core/types/primitive/validator/result.rb +78 -0
- data/lib/smart_core/types/system.rb +21 -5
- data/lib/smart_core/types/value.rb +17 -0
- data/lib/smart_core/types/value/big_decimal.rb +28 -0
- data/lib/smart_core/types/value/comparable.rb +13 -0
- data/lib/smart_core/types/value/date.rb +21 -0
- data/lib/smart_core/types/value/date_time.rb +21 -0
- data/lib/smart_core/types/value/enumerable.rb +13 -0
- data/lib/smart_core/types/value/enumerator.rb +13 -0
- data/lib/smart_core/types/value/enumerator_chain.rb +13 -0
- data/lib/smart_core/types/value/float.rb +6 -2
- data/lib/smart_core/types/value/hash.rb +8 -1
- data/lib/smart_core/types/value/integer.rb +10 -3
- data/lib/smart_core/types/value/io.rb +13 -0
- data/lib/smart_core/types/value/method.rb +9 -0
- data/lib/smart_core/types/value/nil.rb +9 -0
- data/lib/smart_core/types/value/numeric.rb +13 -3
- data/lib/smart_core/types/value/proc.rb +11 -1
- data/lib/smart_core/types/value/range.rb +9 -0
- data/lib/smart_core/types/value/rational.rb +13 -0
- data/lib/smart_core/types/value/set.rb +13 -0
- data/lib/smart_core/types/value/string.rb +7 -1
- data/lib/smart_core/types/value/string_io.rb +13 -0
- data/lib/smart_core/types/value/symbol.rb +7 -1
- data/lib/smart_core/types/value/text.rb +16 -1
- data/lib/smart_core/types/value/time.rb +21 -0
- data/lib/smart_core/types/value/time_based.rb +29 -0
- data/lib/smart_core/types/value/unbound_method.rb +9 -0
- data/lib/smart_core/types/version.rb +2 -2
- data/smart_types.gemspec +6 -5
- metadata +64 -22
- data/lib/smart_core/types/primitive/mult_checker.rb +0 -31
- data/lib/smart_core/types/primitive/nilable_checker.rb +0 -37
- data/lib/smart_core/types/primitive/sum_checker.rb +0 -31
- data/lib/smart_core/types/system/definition_dsl.rb +0 -40
- data/lib/smart_core/types/system/producer_dsl.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5f0c7f2b54ceaa7fe20e85d7d280b64b8310eb5f4fa802d11052074e6b10f96
|
4
|
+
data.tar.gz: 021c3c6194fb4f54246f4a44a7c548ce9da0790a66b95e0a060547e73efeaf3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e2fc86bcea2292570d2c51e9b95ead6ecc30f8251db75a61fda088c1a84bdb15cea65fdc478728869fb5e5e56b7cddb774938cae38c60e4dee70197e6c1c7f3
|
7
|
+
data.tar.gz: c7b27e2f70f3f8eac851f63365b3287a2c7aeb8f7f999679daa715d5ff7de93b32bd6204ea67f6af2c2ea1e5ccd569027051674c9266c62ff7d425c55692619a
|
data/.rubocop.yml
CHANGED
@@ -5,7 +5,8 @@ inherit_gem:
|
|
5
5
|
- lib/rubocop.rspec.yml
|
6
6
|
|
7
7
|
AllCops:
|
8
|
-
TargetRubyVersion: 2.
|
8
|
+
TargetRubyVersion: 2.7.2
|
9
|
+
NewCops: enable
|
9
10
|
Include:
|
10
11
|
- lib/**/*.rb
|
11
12
|
- spec/**/*.rb
|
@@ -13,3 +14,11 @@ AllCops:
|
|
13
14
|
- Rakefile
|
14
15
|
- smart_types.gemspec
|
15
16
|
- bin/console
|
17
|
+
|
18
|
+
# NOTE: support for old ruby versions
|
19
|
+
Style/RedundantBegin:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
# NOTE: used only in specs and it is ok in specs
|
23
|
+
Lint/EmptyBlock:
|
24
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -2,17 +2,18 @@
|
|
2
2
|
language: ruby
|
3
3
|
cache: bundler
|
4
4
|
os: linux
|
5
|
-
|
5
|
+
dist: xenial
|
6
|
+
before_install: gem install bundler
|
6
7
|
script:
|
7
8
|
- bundle exec rake rubocop
|
8
9
|
- bundle exec rake rspec
|
9
10
|
jobs:
|
10
11
|
fast_finish: true
|
11
12
|
include:
|
12
|
-
- rvm: 2.4.
|
13
|
-
- rvm: 2.5.
|
14
|
-
- rvm: 2.6.
|
15
|
-
- rvm: 2.7.
|
13
|
+
- rvm: 2.4.10
|
14
|
+
- rvm: 2.5.8
|
15
|
+
- rvm: 2.6.6
|
16
|
+
- rvm: 2.7.1
|
16
17
|
- rvm: ruby-head
|
17
18
|
- rvm: jruby-head
|
18
19
|
allow_failures:
|
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
## [0.2.0] - 2020-11-21
|
5
|
+
### Added
|
6
|
+
- Brand new **Type invariant API**:
|
7
|
+
- globally refactored validation logic (with backward compatability for `#valid?(value)` method);
|
8
|
+
- new type definition DSL: `.invariant(name)` and `.invariant_chain(name)`;
|
9
|
+
- chained invariants will be invoked according to the definition order (second invokation
|
10
|
+
depends on previous successful invariant check);
|
11
|
+
- new validation API: `validate(value)` (with `#errors` support based on invariant names);
|
12
|
+
- at this moment Invariant API is supported only by primitive types (type sum and type multiplication support coming soon);
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
|
16
|
+
- Updated `smart_engine` dependency (to `~> 0.7`) (need `SmartCore::Engine::Atom`);
|
17
|
+
|
18
|
+
## [0.1.0] - 2020-05-05
|
19
|
+
- Release :)
|
data/Gemfile.lock
CHANGED
@@ -1,77 +1,103 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
smart_types (0.
|
5
|
-
smart_engine (~> 0.
|
4
|
+
smart_types (0.2.0)
|
5
|
+
smart_engine (~> 0.7)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
10
|
+
activesupport (6.0.3.4)
|
11
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
+
i18n (>= 0.7, < 2)
|
13
|
+
minitest (~> 5.1)
|
14
|
+
tzinfo (~> 1.1)
|
15
|
+
zeitwerk (~> 2.2, >= 2.2.2)
|
16
|
+
armitage-rubocop (1.3.1.1)
|
17
|
+
rubocop (= 1.3.1)
|
18
|
+
rubocop-performance (= 1.9.0)
|
19
|
+
rubocop-rails (= 2.8.1)
|
20
|
+
rubocop-rake (= 0.5.1)
|
21
|
+
rubocop-rspec (= 2.0.0)
|
22
|
+
ast (2.4.1)
|
23
|
+
coderay (1.1.3)
|
24
|
+
concurrent-ruby (1.1.7)
|
25
|
+
diff-lcs (1.4.4)
|
18
26
|
docile (1.3.2)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
27
|
+
i18n (1.8.5)
|
28
|
+
concurrent-ruby (~> 1.0)
|
29
|
+
method_source (1.0.0)
|
30
|
+
minitest (5.14.2)
|
31
|
+
parallel (1.20.0)
|
32
|
+
parser (2.7.2.0)
|
33
|
+
ast (~> 2.4.1)
|
34
|
+
pry (0.13.1)
|
35
|
+
coderay (~> 1.1)
|
36
|
+
method_source (~> 1.0)
|
37
|
+
rack (2.2.3)
|
25
38
|
rainbow (3.0.0)
|
26
39
|
rake (13.0.1)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
rspec-
|
31
|
-
|
32
|
-
rspec-
|
33
|
-
rspec-
|
40
|
+
regexp_parser (1.8.2)
|
41
|
+
rexml (3.2.4)
|
42
|
+
rspec (3.10.0)
|
43
|
+
rspec-core (~> 3.10.0)
|
44
|
+
rspec-expectations (~> 3.10.0)
|
45
|
+
rspec-mocks (~> 3.10.0)
|
46
|
+
rspec-core (3.10.0)
|
47
|
+
rspec-support (~> 3.10.0)
|
48
|
+
rspec-expectations (3.10.0)
|
34
49
|
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-mocks (3.
|
50
|
+
rspec-support (~> 3.10.0)
|
51
|
+
rspec-mocks (3.10.0)
|
37
52
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-support (3.
|
40
|
-
rubocop (
|
41
|
-
jaro_winkler (~> 1.5.1)
|
53
|
+
rspec-support (~> 3.10.0)
|
54
|
+
rspec-support (3.10.0)
|
55
|
+
rubocop (1.3.1)
|
42
56
|
parallel (~> 1.10)
|
43
|
-
parser (>= 2.7.
|
57
|
+
parser (>= 2.7.1.5)
|
44
58
|
rainbow (>= 2.2.2, < 4.0)
|
59
|
+
regexp_parser (>= 1.8)
|
60
|
+
rexml
|
61
|
+
rubocop-ast (>= 1.1.1)
|
45
62
|
ruby-progressbar (~> 1.7)
|
46
|
-
unicode-display_width (>= 1.4.0, <
|
47
|
-
rubocop-
|
48
|
-
|
49
|
-
rubocop-
|
63
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
64
|
+
rubocop-ast (1.1.1)
|
65
|
+
parser (>= 2.7.1.5)
|
66
|
+
rubocop-performance (1.9.0)
|
67
|
+
rubocop (>= 0.90.0, < 2.0)
|
68
|
+
rubocop-ast (>= 0.4.0)
|
69
|
+
rubocop-rails (2.8.1)
|
70
|
+
activesupport (>= 4.2.0)
|
50
71
|
rack (>= 1.1)
|
51
|
-
rubocop (>= 0.
|
52
|
-
rubocop-rake (0.5.
|
72
|
+
rubocop (>= 0.87.0)
|
73
|
+
rubocop-rake (0.5.1)
|
53
74
|
rubocop
|
54
|
-
rubocop-rspec (
|
55
|
-
rubocop (
|
75
|
+
rubocop-rspec (2.0.0)
|
76
|
+
rubocop (~> 1.0)
|
77
|
+
rubocop-ast (>= 1.1.0)
|
56
78
|
ruby-progressbar (1.10.1)
|
57
|
-
simplecov (0.
|
79
|
+
simplecov (0.19.1)
|
58
80
|
docile (~> 1.1)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
81
|
+
simplecov-html (~> 0.11)
|
82
|
+
simplecov-html (0.12.3)
|
83
|
+
smart_engine (0.8.0)
|
84
|
+
thread_safe (0.3.6)
|
85
|
+
tzinfo (1.2.8)
|
86
|
+
thread_safe (~> 0.1)
|
87
|
+
unicode-display_width (1.7.0)
|
88
|
+
zeitwerk (2.4.1)
|
64
89
|
|
65
90
|
PLATFORMS
|
66
91
|
ruby
|
67
92
|
|
68
93
|
DEPENDENCIES
|
69
|
-
armitage-rubocop (~>
|
94
|
+
armitage-rubocop (~> 1.3)
|
70
95
|
bundler (~> 2.1)
|
96
|
+
pry (~> 0.13)
|
71
97
|
rake (~> 13.0)
|
72
|
-
rspec (~> 3.
|
73
|
-
simplecov (~> 0.
|
98
|
+
rspec (~> 3.10)
|
99
|
+
simplecov (~> 0.19)
|
74
100
|
smart_types!
|
75
101
|
|
76
102
|
BUNDLED WITH
|
77
|
-
2.1.
|
103
|
+
2.1.4
|
data/README.md
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
> A set of objects that acts like types (type checking and type casting) with a support for basic type algebra.
|
4
4
|
|
5
|
-
|
5
|
+
Minimalistic type system for any ruby project. Supports custom type definitioning,
|
6
6
|
type validation, type casting and type categorizing. Provides a set of commonly used type
|
7
7
|
categories and general purpose types. Has a flexible and simplest type definition toolchain.
|
8
8
|
|
9
|
-
Just add and use :) Enjoy! :)
|
10
|
-
|
11
9
|
## Installation
|
12
10
|
|
13
11
|
```ruby
|
@@ -41,77 +39,349 @@ type4 = type1 & type2
|
|
41
39
|
|
42
40
|
## Supported types
|
43
41
|
|
44
|
-
-
|
42
|
+
- Primitives
|
45
43
|
|
46
44
|
```ruby
|
47
45
|
SmartCore::Types::Value::Any
|
46
|
+
SmartCore::Types::Value::Nil
|
48
47
|
SmartCore::Types::Value::String
|
49
48
|
SmartCore::Types::Value::Symbol
|
50
49
|
SmartCore::Types::Value::Text
|
51
50
|
SmartCore::Types::Value::Integer
|
52
51
|
SmartCore::Types::Value::Float
|
53
52
|
SmartCore::Types::Value::Numeric
|
53
|
+
SmartCore::Types::Value::BigDecimal
|
54
54
|
SmartCore::Types::Value::Boolean
|
55
55
|
SmartCore::Types::Value::Array
|
56
56
|
SmartCore::Types::Value::Hash
|
57
57
|
SmartCore::Types::Value::Proc
|
58
58
|
SmartCore::Types::Value::Class
|
59
59
|
SmartCore::Types::Value::Module
|
60
|
+
SmartCore::Types::Value::Time
|
61
|
+
SmartCore::Types::Value::DateTime
|
62
|
+
SmartCore::Types::Value::Date
|
63
|
+
SmartCore::Types::Value::TimeBased
|
60
64
|
```
|
61
65
|
|
62
66
|
---
|
63
67
|
|
64
68
|
## Nilable types
|
65
69
|
|
70
|
+
- invoke `.nilable` on any type object:
|
71
|
+
|
66
72
|
```ruby
|
67
|
-
SmartCore::Types::Value::Any.nilable
|
68
73
|
SmartCore::Types::Value::String.nilable
|
69
|
-
|
70
|
-
SmartCore::Types::Value::
|
71
|
-
|
72
|
-
SmartCore::Types::Value::Float.nilable
|
73
|
-
SmartCore::Types::Value::Numeric.nilable
|
74
|
-
SmartCore::Types::Value::Boolean.nilable
|
75
|
-
SmartCore::Types::Value::Array.nilable
|
76
|
-
SmartCore::Types::Value::Hash.nilable
|
77
|
-
SmartCore::Types::Value::Proc.nilable
|
78
|
-
SmartCore::Types::Value::Class.nilable
|
79
|
-
SmartCore::Types::Value::Module.nilable
|
74
|
+
# -- or --
|
75
|
+
SmartCore::Types::Value::Time.nilable
|
76
|
+
# and etc.
|
80
77
|
```
|
81
78
|
|
82
79
|
---
|
83
80
|
|
84
|
-
##
|
81
|
+
## Custom type definition
|
82
|
+
|
83
|
+
Type definition is a composition of:
|
84
|
+
|
85
|
+
- type checker (required);
|
86
|
+
- type caster (optional);
|
87
|
+
- type invariants (optional);
|
88
|
+
- type invariant chains (optional);
|
89
|
+
|
90
|
+
Invariant is a custom validation block that will work as a logical value checker. You can have as much invariants as you want.
|
91
|
+
|
92
|
+
Type invariants does not depends on each other (invariant defined out from chain does not depends on other invariants);
|
93
|
+
|
94
|
+
Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
|
95
|
+
|
96
|
+
**!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
|
97
|
+
Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
|
98
|
+
|
99
|
+
Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section). Invariant error code pattern:
|
100
|
+
- for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
|
101
|
+
- for single invariant: `TypeName.invariant_name`;
|
102
|
+
|
103
|
+
#### Primitive type definition
|
85
104
|
|
86
105
|
```ruby
|
87
106
|
# documentation is coming
|
107
|
+
|
108
|
+
# example:
|
109
|
+
SmartCore::Types::Value.define_type(:String) do |type|
|
110
|
+
type.define_checker do |value|
|
111
|
+
value.is_a?(::String)
|
112
|
+
end
|
113
|
+
|
114
|
+
type.define_caster do |value|
|
115
|
+
value.to_s
|
116
|
+
end
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
#### With type invariants
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
SmartCore::Types::Value.define_type(:String) do |type|
|
124
|
+
type.define_checker do |value|
|
125
|
+
value.is_a?(::String)
|
126
|
+
end
|
127
|
+
|
128
|
+
type.define_caster do |value|
|
129
|
+
value.to_s
|
130
|
+
end
|
131
|
+
|
132
|
+
# NOTE:
|
133
|
+
# invariant defined out from chain does not depends on other invariants
|
134
|
+
type.invariant(:uncensored_content) do |value|
|
135
|
+
!value.include?('uncensored_word')
|
136
|
+
end
|
137
|
+
|
138
|
+
type.invariant(:filled) do |value|
|
139
|
+
value != ''
|
140
|
+
end
|
141
|
+
|
142
|
+
type.invariant_chain(:password) do
|
143
|
+
invariant(:should_present) { |value| value != '' }
|
144
|
+
invariant(:should_have_numbers) { |value| v.match?(/[0-9]+/) }
|
145
|
+
# NOTE:
|
146
|
+
# inside a chain each next invariant invokation
|
147
|
+
# depends on previous successful invariant check
|
148
|
+
end
|
149
|
+
end
|
88
150
|
```
|
89
151
|
|
90
152
|
---
|
91
153
|
|
92
|
-
##
|
154
|
+
## Type validation
|
155
|
+
|
156
|
+
Type validation reflects on two APIs:
|
157
|
+
|
158
|
+
- type checker ([how to define type checkers](#custom-type-definition));
|
159
|
+
- type invariants (invariants and invariant chains) ([how to define type invariants](#custom-type-definition));
|
160
|
+
|
161
|
+
Type invariants does not depends on each other (invariant defined out from the chain does not depends on other invariants);
|
162
|
+
|
163
|
+
Invariants inside invariant chains will be invoked in order they was defined and each internal invariant depends on the valid previous invairant check.
|
164
|
+
|
165
|
+
**!IMPORTANT!** Type sum and type multiplication does not support invariant checking and custom invariant definitioning at this moment.
|
166
|
+
Type sum and type mult ignores type invariants in their validation logic (currently this functionality in development yet).
|
167
|
+
|
168
|
+
Invariant checking is a special validation layer (see [#type validation](#type-validation) readme section) and represents a set of error codes in result object;
|
169
|
+
|
170
|
+
Type valdiation interface:
|
171
|
+
|
172
|
+
- `valid?(value)` - validates value and returns `true` or `false`;
|
173
|
+
- returns `ture` only if the type checker returns `true` and all invariants are valid;
|
174
|
+
- `validate(value)` - validates value and returns the monadic result object:
|
175
|
+
- `SmartCore::Types::Primitive::Validator::Result` for primitive types;
|
176
|
+
- `SmartCore::Types::Primitive::SumValidator::Result` for sum-based types;
|
177
|
+
- `SmartCore::Types::Primitive::MultValidator::Result` for mult-based types;
|
178
|
+
- `SmartCore::Types::Primitive::NilableValidator::Result` for nilable types;
|
179
|
+
- `validate!(value)` - validates value and returns nothing (for successful validation) or
|
180
|
+
raises an exception (`SmartCore::Types::TypeError`) (for unsuccessful validation);
|
181
|
+
|
182
|
+
Validation result object interface:
|
183
|
+
|
184
|
+
- `#success?` / `#failure?` (`#success?` is a combination of `valid_check? && valid_invariants?`; `#failure?` - is an opposite of `#success?`);
|
185
|
+
- `#valid_check?` (valid type checker or not);
|
186
|
+
- `#valid_invariants?` (`false` if at least one invariant is invalid);
|
187
|
+
- `#errors` (the same as `#invariant_errors` and the same as `#error_codes`) - an array of failed invariant names;
|
188
|
+
- error code patterns:
|
189
|
+
- for invariant chains: `TypeName.invariant_chain_name.invariant_name`;
|
190
|
+
- for single invariant: `TypeName.invariant_name`;
|
191
|
+
- `#checked_value` (the same as `#value`) - checked value :)
|
192
|
+
|
93
193
|
|
94
194
|
```ruby
|
95
|
-
#
|
195
|
+
SmartCore::Types::Value::String.valid?('test123') # => true
|
196
|
+
SmartCore::Types::Value::String.valid?(123.45) # => false
|
197
|
+
```
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
result = SmartCore::Types::Value::String.validate('test')
|
201
|
+
|
202
|
+
result.checked_value # => 'test'
|
203
|
+
# --- same as: ---
|
204
|
+
result.value
|
205
|
+
|
206
|
+
result.success? # => false (valid_check? && valid_invariants?)
|
207
|
+
result.failure? # => true
|
208
|
+
|
209
|
+
result.valid_check? # => true
|
210
|
+
result.valid_invariants? # => false
|
211
|
+
|
212
|
+
# invariant errors:
|
213
|
+
result.errors # => ['String.password.should_have_numbers']
|
214
|
+
# -- same as: ---
|
215
|
+
result.invariant_errors
|
216
|
+
# -- same as: ---
|
217
|
+
result.error_codes
|
218
|
+
```
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
result = SmartCore::Types::Value::String.validate('test1234')
|
222
|
+
result.success? # => true
|
223
|
+
result.errors # => []
|
224
|
+
```
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
SmartCore::Types::Value::String.validate!('test') # => SmartCore::Types::TypeError
|
228
|
+
```
|
229
|
+
|
230
|
+
---
|
231
|
+
|
232
|
+
## Type casting
|
233
|
+
|
234
|
+
```
|
235
|
+
SmartCore::Types::Value::String.cast(123) # => "123"
|
236
|
+
SmartCore::Types::Value::Float.cast('55') # => 55.0
|
96
237
|
```
|
97
238
|
|
98
239
|
---
|
99
240
|
|
100
241
|
## Basic type algebra
|
101
242
|
|
243
|
+
> (type sum and type multiplication does not support invariants at this moment (in development yet));
|
244
|
+
|
102
245
|
```ruby
|
103
246
|
# documentation is coming
|
247
|
+
|
248
|
+
# how to define primitive type sum:
|
249
|
+
SmartCore::Types::Value::Text = SmartCore::Types::Value::String | SmartCore::Types::Value::Symbol
|
250
|
+
SmartCore::Types::Value::Numeric = SmartCore::Types::Value::Float | SmartCore::Types::Value::Integer
|
251
|
+
|
252
|
+
# how to define primitive type multiplication:
|
253
|
+
SmartCore::Types::Value::CryptoString = SmartCore::Types::Value::NumberdString & SmartCore::Types::Value::SymbolicString
|
104
254
|
```
|
105
255
|
|
106
256
|
---
|
107
257
|
|
108
|
-
##
|
258
|
+
## Roadmap
|
259
|
+
|
260
|
+
- type configuration:
|
109
261
|
|
110
262
|
```ruby
|
111
|
-
|
263
|
+
SmartCore::Types::Value.type(:Time) do |type|
|
264
|
+
type.configuration do |config| # config definition
|
265
|
+
setting :iso, :rfc2822
|
266
|
+
# TODO: think about a more convinient DSL
|
267
|
+
end
|
268
|
+
|
269
|
+
type.define_caster do |value, config| # config usage
|
270
|
+
case config.standard
|
271
|
+
when :rfc2822
|
272
|
+
::Time.rfc2822(value)
|
273
|
+
else
|
274
|
+
# ...
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
112
278
|
```
|
113
279
|
|
114
|
-
|
280
|
+
- pipelined type caster definition for the sum-based types:
|
281
|
+
|
282
|
+
```ruby
|
283
|
+
SmartCore::Types::Value::TimeLike = SmartCore::Types::System.type_sum(
|
284
|
+
SmartCore::Types::Time,
|
285
|
+
SmartCore::Types::DateTime,
|
286
|
+
SmartCore::Types::Date,
|
287
|
+
) do |type|
|
288
|
+
type.define_caster(:pipelined) # try Time.cast => try DateTime.cast => try Date.cast
|
289
|
+
end
|
290
|
+
```
|
291
|
+
|
292
|
+
- namespaced type errors:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
# before:
|
296
|
+
SmartCore::Types::Value::Boolean.validate!(123)
|
297
|
+
# => SmartCore::Types::TypeError
|
298
|
+
SmartCore::Types::Value::Class.cast(123)
|
299
|
+
# => SmartCore::Types::TypeCastingError
|
300
|
+
|
301
|
+
# after:
|
302
|
+
SmartCore::Types::Value::Boolean.validate!(123)
|
303
|
+
# => SmartCore::Types::Value::Boolean::TypeError
|
304
|
+
# (inheritance tree: Types::Value::<Type>::TypeError => Types::Value::TypeError => Types::TypeError)
|
305
|
+
|
306
|
+
SmartCore::Types::Value::Class.cast(123)
|
307
|
+
# => SmartCore::Types::Value::Class::TypeCastingError
|
308
|
+
# (inheritance tree: the same as above)
|
309
|
+
```
|
310
|
+
|
311
|
+
- type refinements:
|
312
|
+
|
313
|
+
```ruby
|
314
|
+
SmartCore::Types::Value::Time.refine_checker do |value, original_checker|
|
315
|
+
# new type checker
|
316
|
+
end
|
317
|
+
|
318
|
+
SmartCore::Types::Value::Time.refine_caster do |value, original_caster|
|
319
|
+
# new type caster
|
320
|
+
end
|
321
|
+
|
322
|
+
# .refine_invariant
|
323
|
+
# .refine_invariant_chain
|
324
|
+
```
|
325
|
+
|
326
|
+
- options for type casters:
|
327
|
+
|
328
|
+
```ruby
|
329
|
+
SmartCore::Types::Value.define_type(:Date) do |type|
|
330
|
+
type.define_caster do |value, options = {}| # options goes here
|
331
|
+
iso = options.fetch(:iso, nil)
|
332
|
+
iso ? ::Date.pasre(value, iso) : ::Date.parse(value)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
# usage:
|
337
|
+
SmartCore::Types::Value::Date.cast('2020-01-01', { iso: :rfc3339 })
|
338
|
+
```
|
339
|
+
|
340
|
+
- new types:
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
SmartCore::Types::Value::Method
|
344
|
+
SmartCore::Types::Value::UnboundMethod
|
345
|
+
SmartCore::Types::Value::Enumerable
|
346
|
+
SmartCore::Types::Value::Comparable
|
347
|
+
SmartCore::Types::Value::Enumerator
|
348
|
+
SmartCore::Types::Value::EnumeratorChain
|
349
|
+
SmartCore::Types::Value::Range
|
350
|
+
SmartCore::Types::Value::Rational
|
351
|
+
SmartCore::Types::Value::Set
|
352
|
+
SmartCore::Types::Value::SortedSet
|
353
|
+
SmartCore::Types::Value::IO
|
354
|
+
SmartCore::Types::Value::StringIO
|
355
|
+
SmartCore::Types::Struct::Schema
|
356
|
+
SmartCore::Types::Struct::JSONSchema
|
357
|
+
SmartCore::Types::Struct::StrictArray
|
358
|
+
SmartCore::Types::Struct::StrictHash
|
359
|
+
SmartCore::Types::Struct::Map
|
360
|
+
SmartCore::Types::Variative::Enum
|
361
|
+
SmartCore::Types::Variative::Variant
|
362
|
+
SmartCore::Types::Protocol::InstanceOf
|
363
|
+
SmartCore::Types::Protocol::Interface
|
364
|
+
SmartCore::Types::Protocol::Ancestors
|
365
|
+
SmartCore::Types::Protocol::Enumerable
|
366
|
+
SmartCore::Types::Protocol::Comparable
|
367
|
+
SmartCore::Types::Protocol::Forwardable
|
368
|
+
SmartCore::Types::Protocol::Callable
|
369
|
+
```
|
370
|
+
|
371
|
+
- support for type of empty non-defined type (`SmartCore::Types::Primitive::Undefined`);
|
372
|
+
- constrained types;
|
373
|
+
- moudle-based type system integration;
|
374
|
+
- constructor implementation and support;
|
375
|
+
- support for invariant checking (and custom definitioning) in sum-types;
|
376
|
+
- to provide a type comparability and compatability between all passed types
|
377
|
+
you should provide `type.reconcilable { |value, *types| .... }` setting;
|
378
|
+
- `type.reconcilable` should be accesible for type sum and type mult definitions;
|
379
|
+
- (**preliminarily**) invariants of the concrete passed type should be valid for sucessful invariant check;
|
380
|
+
- support for invariant checking (and definitioning) in mult-types;
|
381
|
+
- to provide a type comparability and compatability between all passed types
|
382
|
+
you should provide `type.reconcilable { |value, *types| .... }` setting;
|
383
|
+
- `type.reconcilable` should be accesible for type sum and type mult definitions;
|
384
|
+
- (**preliminarily**) all invariants of all types should be valid for sucessful invariant check;
|
115
385
|
|
116
386
|
## Contributing
|
117
387
|
|