dry-types 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/----please-don-t-ask-for-support-via-issues.md +10 -0
  3. data/.github/ISSUE_TEMPLATE/---bug-report.md +34 -0
  4. data/.github/ISSUE_TEMPLATE/---feature-request.md +18 -0
  5. data/.travis.yml +10 -4
  6. data/CHANGELOG.md +68 -0
  7. data/Gemfile +8 -6
  8. data/README.md +2 -2
  9. data/docsite/source/array-with-member.html.md +13 -0
  10. data/docsite/source/built-in-types.html.md +116 -0
  11. data/docsite/source/constraints.html.md +31 -0
  12. data/docsite/source/custom-types.html.md +93 -0
  13. data/docsite/source/default-values.html.md +91 -0
  14. data/docsite/source/enum.html.md +69 -0
  15. data/docsite/source/getting-started.html.md +57 -0
  16. data/docsite/source/hash-schemas.html.md +169 -0
  17. data/docsite/source/index.html.md +155 -0
  18. data/docsite/source/map.html.md +17 -0
  19. data/docsite/source/optional-values.html.md +96 -0
  20. data/docsite/source/sum.html.md +21 -0
  21. data/lib/dry/types.rb +7 -2
  22. data/lib/dry/types/array/member.rb +1 -1
  23. data/lib/dry/types/builder_methods.rb +18 -8
  24. data/lib/dry/types/constructor.rb +2 -29
  25. data/lib/dry/types/decorator.rb +1 -1
  26. data/lib/dry/types/extensions.rb +4 -0
  27. data/lib/dry/types/extensions/monads.rb +29 -0
  28. data/lib/dry/types/hash.rb +2 -1
  29. data/lib/dry/types/lax.rb +1 -1
  30. data/lib/dry/types/params.rb +5 -0
  31. data/lib/dry/types/predicate_inferrer.rb +197 -0
  32. data/lib/dry/types/predicate_registry.rb +34 -0
  33. data/lib/dry/types/primitive_inferrer.rb +97 -0
  34. data/lib/dry/types/printer.rb +7 -3
  35. data/lib/dry/types/version.rb +1 -1
  36. metadata +48 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 689634e9152c629af622ef69379633b674b6c60b7f5cd87093894de7ee8ce571
4
- data.tar.gz: a23593e6c4d904343dadd46f919cfead42b45fbe963995380712f4c6a8e719fd
3
+ metadata.gz: 87e78ecf331ef9c4d95759bf28c2694e413df18fd0397d3c3c51380320328417
4
+ data.tar.gz: ca84bf0a23d37d7f0beda024d573852d2a0701a76f54dee2255166981bd716c5
5
5
  SHA512:
6
- metadata.gz: 88fd3e79ea403515fe242baa57c6824757bdc0b04f99054a9da2394c745cce54415fc3c260b35e49eed8a5240f78614efe92e052f6e6bde0e1f9b961a04f41ac
7
- data.tar.gz: 3445b5726dd5325261965409883b6830450f3d710ae2b0a7be411b0d45cb25d3550a25827d9f0661dfbfd0fd55f15954d77335312237c3bf754ca7af5eae6079
6
+ metadata.gz: 8ae0d71644bfc391ada28229a68010a378b07e252c6ea5fdc27327065cdfc980b27a25bd9d63068966803a800a262958ef4ea0fc0296d4e865534e3fb3458dc8
7
+ data.tar.gz: a1e899fb498a414f3920f9a19bc8ca22fc4db2bf7e6063a7baca389c528c0fb4d9114522d57606d7143c872b6847b9f1134f04326d1dc5ba694853a0c3977390
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: "⚠️ Please don't ask for support via issues"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: ''
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: "\U0001F41B Bug report"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Before you submit this: WE ONLY ACCEPT BUG REPORTS AND FEATURE REQUESTS**
11
+
12
+ For more information see [our contribution guidelines](https://github.com/rom-rb/rom/blob/master/CONTRIBUTING.md)
13
+
14
+ **Before you report**
15
+
16
+ :warning: If you have a problem related to a schema, please **report it under [dry-schema issues](https://github.com/dry-rb/dry-schema/issues/new?assignees=&labels=bug&template=---bug-report.md&title=)** instead.
17
+
18
+ **Describe the bug**
19
+
20
+ A clear and concise description of what the bug is.
21
+
22
+ **To Reproduce**
23
+
24
+ Provide detailed steps to reproduce, an executable script would be best.
25
+
26
+ **Expected behavior**
27
+
28
+ A clear and concise description of what you expected to happen.
29
+
30
+ **Your environment**
31
+
32
+ - Affects my production application: **YES/NO**
33
+ - Ruby version: ...
34
+ - OS: ...
@@ -0,0 +1,18 @@
1
+ ---
2
+ name: "\U0001F6E0 Feature request"
3
+ about: See CONTRIBUTING.md for more information
4
+ title: ''
5
+ labels: feature
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ Summary of what the feature is supposed to do.
11
+
12
+ ## Examples
13
+
14
+ Code examples showing how the feature could be used.
15
+
16
+ ## Resources
17
+
18
+ Additional information, like a link to the discussion forum thread where the feature was discussed etc.
data/.travis.yml CHANGED
@@ -10,13 +10,19 @@ after_script:
10
10
  script:
11
11
  - bundle exec rake
12
12
  rvm:
13
- - 2.6.3
14
- - 2.5.5
15
- - 2.4.6
16
- - jruby-9.2.7.0
13
+ - 2.6.5
14
+ - 2.5.7
15
+ - 2.4.9
16
+ - ruby-head
17
17
  env:
18
18
  global:
19
19
  - COVERAGE=true
20
+ matrix:
21
+ allow_failures:
22
+ - rvm: ruby-head
23
+ include:
24
+ - rvm: jruby-9.2.8.0
25
+ jdk: openjdk8
20
26
  notifications:
21
27
  email: false
22
28
  webhooks:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,71 @@
1
+ # 1.2.0 2019-10-06
2
+
3
+ ## Changed
4
+
5
+ - `Dry::Types.[]` used to work with classes, now it's deprecated (flash-gordon)
6
+
7
+ ## Fixed
8
+
9
+ - Bug with using a `Bool`-named struct as a schema key (flash-gordon)
10
+ - A bunch of issues related to using `meta` on complex types (flash-gordon)
11
+ - `Types.Constructor(...)` returns a `Types::Array` as it should (flash-gordon)
12
+
13
+ ## Added
14
+
15
+ - `Optional::Params` types that coerce empty strings to `nil` (flash-gordon)
16
+ ```ruby
17
+ Dry::Types['optional.params.integer'].('') # => nil
18
+ Dry::Types['optional.params.integer'].('140') # => 140
19
+ Dry::Types['optional.params.integer'].('asd') # => exception!
20
+ ```
21
+ Keep in mind, Dry::Types['optional.params.integer'] and Dry::Types['params.integer'].optional are not the same, the latter doesn't handle empty strings.
22
+ - Predicate inferrer was ported from dry-schema (authored by solnic)
23
+ ```ruby
24
+ require 'dry/types/predicate_inferrer'
25
+ Dry::Types::PredicateInferrer.new[Types::String]
26
+ # => [:str?]
27
+ Dry::Types::PredicateInferrer.new[Types::String | Types::Integer]
28
+ # => [[[:str?], [:int?]]]
29
+ ```
30
+ Note that the API of the predicate inferrer can change in the stable version, it's dictated by the needs of dry-schema so it should be considered as semi-stable. If you depend on it, write specs covering the desired behavior. Another option is copy-and-paste the whole thing to your project.
31
+ - Primitive inferrer was ported from dry-schema (authored by solnic)
32
+ ```ruby
33
+ require 'dry/types/primitive_inferrer'
34
+ Dry::Types::PrimitiveInferrer.new[Types::String]
35
+ # => [String]
36
+ Dry::Types::PrimitiveInferrer.new[Types::String | Types::Integer]
37
+ # => [String, Integer]
38
+ Dry::Types::PrimitiveInferrer.new[Types::String.optional]
39
+ # => [NilClass, String]
40
+ ```
41
+ The primitive inferrer should be stable by now, you can rely on it.
42
+ - The `monads` extension adds `Dry::Types::Result#to_monad`. This makes it compatible with do notation from dry-monads. Load it with `Dry::Types.load_extensions(:monads)` (skryukov)
43
+
44
+ ```ruby
45
+ Types = Dry.Types
46
+ Dry::Types.load_extensions(:monads)
47
+
48
+ class AddTen
49
+ include Dry::Monads[:result, :do]
50
+
51
+ def call(input)
52
+ integer = yield Types::Coercible::Integer.try(input)
53
+
54
+ Success(integer + 10)
55
+ end
56
+ end
57
+ ```
58
+
59
+ [Compare v1.1.1...v1.2.0](https://github.com/dry-rb/dry-types/compare/v1.1.1...v1.2.0)
60
+
61
+ # 1.1.1 2019-07-26
62
+
63
+ ## Fixed
64
+
65
+ - A bug where meta was lost for lax array types (flash-gordon)
66
+
67
+ [Compare v1.1.0...v1.1.1](https://github.com/dry-rb/dry-types/compare/v1.1.0...v1.1.1)
68
+
1
69
  # 1.1.0 2019-07-02
2
70
 
3
71
  ## Added
data/Gemfile CHANGED
@@ -18,10 +18,12 @@ group :tools do
18
18
  end
19
19
 
20
20
  group :benchmarks do
21
- gem 'attrio'
22
- gem 'benchmark-ips'
23
- gem 'dry-struct'
24
- gem 'fast_attributes'
25
- gem 'hotch'
26
- gem 'virtus'
21
+ platform :mri do
22
+ gem 'attrio'
23
+ gem 'benchmark-ips'
24
+ gem 'dry-struct'
25
+ gem 'fast_attributes'
26
+ gem 'hotch'
27
+ gem 'virtus'
28
+ end
27
29
  end
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [gem]: https://rubygems.org/gems/dry-types
2
- [travis]: https://travis-ci.org/dry-rb/dry-types
2
+ [travis]: https://travis-ci.com/dry-rb/dry-types
3
3
  [codeclimate]: https://codeclimate.com/github/dry-rb/dry-types
4
4
  [coveralls]: https://coveralls.io/r/dry-rb/dry-types
5
5
  [inchpages]: http://inch-ci.org/github/dry-rb/dry-types
@@ -8,7 +8,7 @@
8
8
  # dry-types [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
9
9
 
10
10
  [![Gem Version](https://badge.fury.io/rb/dry-types.svg)][gem]
11
- [![Build Status](https://travis-ci.org/dry-rb/dry-types.svg?branch=master)][travis]
11
+ [![Build Status](https://travis-ci.com/dry-rb/dry-types.svg?branch=master)][travis]
12
12
  [![Code Climate](https://codeclimate.com/github/dry-rb/dry-types/badges/gpa.svg)][codeclimate]
13
13
  [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-types/badges/coverage.svg)][codeclimate]
14
14
  [![Inline docs](http://inch-ci.org/github/dry-rb/dry-types.svg?branch=master)][inchpages]
@@ -0,0 +1,13 @@
1
+ ---
2
+ title: Array With Member
3
+ layout: gem-single
4
+ name: dry-types
5
+ ---
6
+
7
+ The built-in array type supports defining the member's type:
8
+
9
+ ``` ruby
10
+ PostStatuses = Types::Array.of(Types::Coercible::String)
11
+
12
+ PostStatuses[[:foo, :bar]] # ["foo", "bar"]
13
+ ```
@@ -0,0 +1,116 @@
1
+ ---
2
+ title: Built-in Types
3
+ layout: gem-single
4
+ name: dry-types
5
+ ---
6
+
7
+ Built-in types are grouped under 6 categories:
8
+
9
+ - `nominal` - base type definitions with a primitive class and options
10
+ - `strict` - constrained types with a primitive type check applied to input
11
+ - `coercible` - types with constructors using kernel coercions
12
+ - `params` - types with constructors performing non-strict coercions specific to HTTP parameters
13
+ - `json` - types with constructors performing non-strict coercions specific to JSON
14
+ - `maybe` - types accepting either nil or a specific primitive type
15
+
16
+ ### Categories
17
+
18
+ Assuming you included `Dry::Types` ([see instructions](/gems/dry-types/1.0/getting-started)) in a module called `Types`:
19
+
20
+ * Nominal types:
21
+ - `Types::Nominal::Any`
22
+ - `Types::Nominal::Nil`
23
+ - `Types::Nominal::Symbol`
24
+ - `Types::Nominal::Class`
25
+ - `Types::Nominal::True`
26
+ - `Types::Nominal::False`
27
+ - `Types::Nominal::Bool`
28
+ - `Types::Nominal::Integer`
29
+ - `Types::Nominal::Float`
30
+ - `Types::Nominal::Decimal`
31
+ - `Types::Nominal::String`
32
+ - `Types::Nominal::Date`
33
+ - `Types::Nominal::DateTime`
34
+ - `Types::Nominal::Time`
35
+ - `Types::Nominal::Array`
36
+ - `Types::Nominal::Hash`
37
+
38
+ * `Strict` types will raise an error if passed a value of the wrong type:
39
+ - `Types::Strict::Nil`
40
+ - `Types::Strict::Symbol`
41
+ - `Types::Strict::Class`
42
+ - `Types::Strict::True`
43
+ - `Types::Strict::False`
44
+ - `Types::Strict::Bool`
45
+ - `Types::Strict::Integer`
46
+ - `Types::Strict::Float`
47
+ - `Types::Strict::Decimal`
48
+ - `Types::Strict::String`
49
+ - `Types::Strict::Date`
50
+ - `Types::Strict::DateTime`
51
+ - `Types::Strict::Time`
52
+ - `Types::Strict::Array`
53
+ - `Types::Strict::Hash`
54
+
55
+ > All types in the `strict` category are [constrained](/gems/dry-types/1.0/constraints) by a type-check that is applied to make sure that the input is an instance of the primitive:
56
+
57
+ ``` ruby
58
+ Types::Strict::Integer[1] # => 1
59
+ Types::Strict::Integer['1'] # => raises Dry::Types::ConstraintError
60
+ ```
61
+
62
+ * `Coercible` types will attempt to cast values to the correct class using kernel coercion methods:
63
+ - `Types::Coercible::String`
64
+ - `Types::Coercible::Integer`
65
+ - `Types::Coercible::Float`
66
+ - `Types::Coercible::Decimal`
67
+ - `Types::Coercible::Array`
68
+ - `Types::Coercible::Hash`
69
+
70
+ * Types suitable for `Params` param processing with coercions:
71
+ - `Types::Params::Nil`
72
+ - `Types::Params::Date`
73
+ - `Types::Params::DateTime`
74
+ - `Types::Params::Time`
75
+ - `Types::Params::True`
76
+ - `Types::Params::False`
77
+ - `Types::Params::Bool`
78
+ - `Types::Params::Integer`
79
+ - `Types::Params::Float`
80
+ - `Types::Params::Decimal`
81
+ - `Types::Params::Array`
82
+ - `Types::Params::Hash`
83
+
84
+ * Types suitable for `JSON` processing with coercions:
85
+ - `Types::JSON::Nil`
86
+ - `Types::JSON::Date`
87
+ - `Types::JSON::DateTime`
88
+ - `Types::JSON::Time`
89
+ - `Types::JSON::Decimal`
90
+ - `Types::JSON::Array`
91
+ - `Types::JSON::Hash`
92
+
93
+ * `Maybe` strict types:
94
+ - `Types::Maybe::Strict::Class`
95
+ - `Types::Maybe::Strict::String`
96
+ - `Types::Maybe::Strict::Symbol`
97
+ - `Types::Maybe::Strict::True`
98
+ - `Types::Maybe::Strict::False`
99
+ - `Types::Maybe::Strict::Integer`
100
+ - `Types::Maybe::Strict::Float`
101
+ - `Types::Maybe::Strict::Decimal`
102
+ - `Types::Maybe::Strict::Date`
103
+ - `Types::Maybe::Strict::DateTime`
104
+ - `Types::Maybe::Strict::Time`
105
+ - `Types::Maybe::Strict::Array`
106
+ - `Types::Maybe::Strict::Hash`
107
+
108
+ * `Maybe` coercible types:
109
+ - `Types::Maybe::Coercible::String`
110
+ - `Types::Maybe::Coercible::Integer`
111
+ - `Types::Maybe::Coercible::Float`
112
+ - `Types::Maybe::Coercible::Decimal`
113
+ - `Types::Maybe::Coercible::Array`
114
+ - `Types::Maybe::Coercible::Hash`
115
+
116
+ > `Maybe` types are not available by default - they must be loaded using `Dry::Types.load_extensions(:maybe)`. See [Optional Values](/gems/dry-types/1.0/optional-values) for more information.
@@ -0,0 +1,31 @@
1
+ ---
2
+ title: Constraints
3
+ layout: gem-single
4
+ name: dry-types
5
+ ---
6
+
7
+ You can create constrained types that will use validation rules to check that the input is not violating any of the configured constraints. You can treat it as a lower level guarantee that you're not instantiating objects that are broken.
8
+
9
+ All types support the constraints API, but not all constraints are suitable for a particular primitive, it's up to you to set up constraints that make sense.
10
+
11
+ Under the hood it uses [`dry-logic`](/gems/dry-logic) and all of its predicates are supported.
12
+
13
+ ``` ruby
14
+ string = Types::String.constrained(min_size: 3)
15
+
16
+ string['foo']
17
+ # => "foo"
18
+
19
+ string['fo']
20
+ # => Dry::Types::ConstraintError: "fo" violates constraints
21
+
22
+ email = Types::String.constrained(
23
+ format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
24
+ )
25
+
26
+ email["jane@doe.org"]
27
+ # => "jane@doe.org"
28
+
29
+ email["jane"]
30
+ # => Dry::Types::ConstraintError: "jane" violates constraints
31
+ ```
@@ -0,0 +1,93 @@
1
+ ---
2
+ title: Custom Types
3
+ layout: gem-single
4
+ name: dry-types
5
+ ---
6
+
7
+ There are a bunch of helpers for building your own types based on existing classes and values. These helpers are automatically defined if you're imported types in a module.
8
+
9
+ ### `Types.Instance`
10
+
11
+ `Types.Instance` builds a type that checks if a value has the given class.
12
+
13
+ ```ruby
14
+ range_type = Types.Instance(Range)
15
+ range_type[1..2] # => 1..2
16
+ ```
17
+
18
+ ### `Types.Value`
19
+
20
+ `Types.Value` builds a type that checks a value for equality (using `==`).
21
+
22
+ ```ruby
23
+ valid = Types.Value('valid')
24
+ valid['valid'] # => 'valid'
25
+ valid['invalid']
26
+ # => Dry::Types::ConstraintError: "invalid" violates constraints (eql?("valid", "invalid") failed)
27
+ ```
28
+
29
+ ### `Types.Constant`
30
+
31
+ `Types.Constant` builds a type that checks a value for identity (using `equal?`).
32
+
33
+ ```ruby
34
+ valid = Types.Constant(:valid)
35
+ valid[:valid] # => :valid
36
+ valid[:invalid]
37
+ # => Dry::Types::ConstraintError: :invalid violates constraints (is?(:valid, :invalid) failed)
38
+ ```
39
+
40
+ ### `Types.Constructor`
41
+
42
+ `Types.Constructor` builds a new constructor type for the given class. By default uses the `new` method as a constructor.
43
+
44
+ ```ruby
45
+ user_type = Types.Constructor(User)
46
+
47
+ # It is equivalent to User.new(name: 'John')
48
+ user_type[name: 'John']
49
+
50
+ # Using a block
51
+ user_type = Types.Constructor(User) { |values| User.new(values) }
52
+ ```
53
+
54
+ ### `Types.Nominal`
55
+
56
+ `Types.Nominal` wraps the given class with a simple definition without any behavior attached.
57
+
58
+ ```ruby
59
+ int = Types.Nominal(Integer)
60
+ int[1] # => 1
61
+
62
+ # The type doesn't have any checks
63
+ int['one'] # => 'one'
64
+ ```
65
+
66
+ ### `Types.Hash`
67
+
68
+ `Types.Hash` builds a new hash schema.
69
+
70
+ ```ruby
71
+ # In the full form
72
+ Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer)
73
+
74
+ # Using Types.Hash()
75
+ Types.Hash(:permissive, name: Types::String, age: Types::Coercible::Integer)
76
+ ```
77
+
78
+ ### `Types.Array`
79
+
80
+ `Types.Array` is a shortcut for `Types::Array.of`
81
+
82
+ ```ruby
83
+ ListOfStrings = Types.Array(Types::String)
84
+ ```
85
+
86
+ ### `Types.Interface`
87
+
88
+ `Types.Interface` builds a type that checks a value responds to given methods.
89
+
90
+ ```ruby
91
+ Callable = Types.Interface(:call)
92
+ Contact = Types.Interface(:name, :phone)
93
+ ```