dry-types 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bb3d91a31885a317b8fda3eef46f77b283abb3781c84124cc7ca0a5a2c30104
4
- data.tar.gz: 88cd356e7878080570e5fa659f1403e01d8bc8a9654b3c5cfaf568c851d8e848
3
+ metadata.gz: 689634e9152c629af622ef69379633b674b6c60b7f5cd87093894de7ee8ce571
4
+ data.tar.gz: a23593e6c4d904343dadd46f919cfead42b45fbe963995380712f4c6a8e719fd
5
5
  SHA512:
6
- metadata.gz: 536386eba753a58a499c473d7f9e54da2bccf8597d80e3e225a036fb37acd886e0e9f75ceff497e81e6cb9a47141c2fdf4753f2bd521bf5a53424f768fc0cf0d
7
- data.tar.gz: f74042df53c00159132ff2675206a393ca73a0d48ab84f7e6d58d56a51082e570932591279705ec993056b8e2720fd4572657b7bcb90596a16a7addaa7ac4bcf
6
+ metadata.gz: 88fd3e79ea403515fe242baa57c6824757bdc0b04f99054a9da2394c745cce54415fc3c260b35e49eed8a5240f78614efe92e052f6e6bde0e1f9b961a04f41ac
7
+ data.tar.gz: 3445b5726dd5325261965409883b6830450f3d710ae2b0a7be411b0d45cb25d3550a25827d9f0661dfbfd0fd55f15954d77335312237c3bf754ca7af5eae6079
@@ -1,8 +1,30 @@
1
+ # 1.1.0 2019-07-02
2
+
3
+ ## Added
4
+
5
+ - New builder method `Interface` constructs a type which accepts objects that respond to the given methods (waiting-for-dev)
6
+ ```ruby
7
+ Types = Dry.Types()
8
+ Types::Callable = Types.Interface(:call)
9
+ Types::Callable.valid?(Object.new) # => false
10
+ Types::Callable.valid?(proc {}) # => true
11
+ ```
12
+ - New types: `coercible.symbol`, `params.symbol`, and `json.symbol`, all use `.to_sym` for coercion (waiting-for-dev)
13
+
14
+ ## Fixed
15
+
16
+ - Converting schema keys to maybe types (flash-gordon)
17
+ - Using `Schema#key` and `Array#member` on constuctors (flash-gordon)
18
+ - Using `meta(omittable: true)` within `transform_types` works again but produces a warning, please migrate to `.omittable` or `.required(false)` (flash-gordon)
19
+ - Bug with a constructror defined on top of enum (flash-gordon)
20
+
21
+ [Compare v1.0.1...v1.1.0](https://github.com/dry-rb/dry-types/compare/v1.0.1...v1.1.0)
22
+
1
23
  # 1.0.1 2019-06-04
2
24
 
3
25
  ## Added
4
26
 
5
- - In the case of failure the constructor block can now pass a different value (flash-gordon)
27
+ - In a case of failure the constructor block can now pass a different value (flash-gordon)
6
28
  ```ruby
7
29
  not_empty_string = Types::String.constructor do |value, &failure|
8
30
  value.strip.empty? ? failure.(nil) : value.strip
@@ -21,6 +43,7 @@
21
43
 
22
44
  - [BREAKING] Behavior of built-in constructor types was changed to be more strict. They will always raise an error on failed coercion (flash-gordon)
23
45
  Compare:
46
+
24
47
  ```ruby
25
48
  # 0.15.0
26
49
  Types::Params::Integer.('foo')
@@ -36,7 +59,9 @@
36
59
  ```ruby
37
60
  Types::Params::Integer.('foo') { :invalid } # => :invalid
38
61
  ```
62
+
39
63
  This makes work with coercions more straightforward and way faster.
64
+
40
65
  - [BREAKING] Safe types were renamed to Lax, this name better serves their purpose. The previous name is available but prints a warning (flash-gordon)
41
66
  - [BREAKING] Metadata is now pushed down to the decorated type. It is not likely you will notice a difference but this a breaking change that enables some use cases in rom related to the usage of default types in relations (flash-gordon)
42
67
  - Nominal types are now completely unconstrained. This fixes some inconsistencies when using them with constraints. `Nominal#try` will always return a successful result, for the previous behavior use `Nominal#try_coerce` or switch to strict types with passing a block to `#call` (flash-gordon)
@@ -159,6 +184,7 @@
159
184
  )
160
185
  ```
161
186
  - Key types have API for making keys omittable and back (flash-gordon)
187
+
162
188
  ```ruby
163
189
  # defining a base schema with optional keys
164
190
  lax_hash = Dry::Types['hash'].with_type_transform { |key| key.required(false) }
@@ -168,8 +194,10 @@
168
194
  # keys in user_schema are not required
169
195
  user_schema = lax_hash.schema(name: 'string', age: 'integer')
170
196
  ```
197
+
171
198
  - `Type#optional?` now recognizes more cases where `nil` is an allowed value (flash-gordon)
172
199
  - `Constructor#{prepend,append}` with `<<` and `>>` as aliases. `Constructor#append` works the same way `Constructor#constrcutor` does. `Constuctor#prepend` chains functions in the reverse order, see examples (flash-gordon)
200
+
173
201
  ```ruby
174
202
  to_int = Types::Coercible::Integer
175
203
  inc = to_int.append { |x| x + 2 }
@@ -178,6 +206,7 @@
178
206
  inc = to_int.prepend { |x| x + "2" }
179
207
  inc.("1") # => "1" -> "12" -> 12
180
208
  ```
209
+
181
210
  - Partial schema application for cases when you want to validate only a subset of keys (flash-gordon)
182
211
  This is useful when you want to update a key or two in an already-validated hash. A perfect example is `Dry::Struct#new` where this feature is now used.
183
212
  ```ruby
@@ -189,14 +218,15 @@
189
218
 
190
219
  ## Fixed
191
220
 
192
- * `Hash::Map` now behaves as a constrained type if its values are constrained (flash-gordon)
193
- * `coercible.integer` now doesn't blow up on invalid strings (exterm)
221
+ - `Hash::Map` now behaves as a constrained type if its values are constrained (flash-gordon)
222
+ - `coercible.integer` now doesn't blow up on invalid strings (exterm)
194
223
 
195
224
  [Compare v0.14.0...v0.15.0](https://github.com/dry-rb/dry-types/compare/v0.14.0...v0.15.0)
196
225
 
197
226
  # v0.14.1 2019-03-25
198
227
 
199
228
  ## Fixed
229
+
200
230
  - `coercible.integer` now doesn't blow up on invalid strings (exterm)
201
231
 
202
232
  [Compare v0.14.0...v0.14.1](https://github.com/dry-rb/dry-types/compare/v0.14.0...v0.14.1)
data/Gemfile CHANGED
@@ -14,13 +14,14 @@ end
14
14
 
15
15
  group :tools do
16
16
  gem 'pry-byebug', platform: :mri
17
+ gem 'rubocop'
17
18
  end
18
19
 
19
20
  group :benchmarks do
21
+ gem 'attrio'
20
22
  gem 'benchmark-ips'
23
+ gem 'dry-struct'
24
+ gem 'fast_attributes'
21
25
  gem 'hotch'
22
26
  gem 'virtus'
23
- gem 'fast_attributes'
24
- gem 'attrio'
25
- gem 'dry-struct'
26
27
  end
data/Rakefile CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  task :run_specs do
7
7
  require 'rspec/core'
@@ -7,11 +7,13 @@ require 'dry-types'
7
7
 
8
8
  module SchemaBench
9
9
  def self.hash_schema(type)
10
- Dry::Types['nominal.hash'].public_send(type,
11
- email: Dry::Types['nominal.string'],
12
- age: Dry::Types['params.integer'],
13
- admin: Dry::Types['params.bool'],
14
- address: Dry::Types['nominal.hash'].public_send(type,
10
+ Dry::Types['nominal.hash'].public_send(
11
+ type,
12
+ email: Dry::Types['nominal.string'],
13
+ age: Dry::Types['params.integer'],
14
+ admin: Dry::Types['params.bool'],
15
+ address: Dry::Types['nominal.hash'].public_send(
16
+ type,
15
17
  city: Dry::Types['nominal.string'],
16
18
  street: Dry::Types['nominal.string']
17
19
  )
@@ -31,7 +33,7 @@ module SchemaBench
31
33
  age: '20',
32
34
  admin: '1',
33
35
  address: { city: 'NYC', street: 'Street 1/2' }
34
- }
36
+ }.freeze
35
37
  end
36
38
 
37
39
  require 'benchmark/ips'
@@ -13,4 +13,3 @@ Benchmark.ips do |x|
13
13
  x.report("valid input") { schema.(params) }
14
14
  x.compare!
15
15
  end
16
-
@@ -6,7 +6,7 @@ INVALID_INPUT = {
6
6
  name: :John,
7
7
  age: '20',
8
8
  email: nil
9
- }
9
+ }.freeze
10
10
 
11
11
  profile do
12
12
  10_000.times do
@@ -7,7 +7,7 @@ Schema = Dry::Types['params.hash'].schema(
7
7
  age?: 'coercible.integer'
8
8
  ).lax
9
9
 
10
- ValidInput = { email: 'jane@doe.org', age: '19' }
10
+ ValidInput = { email: 'jane@doe.org', age: '19' }.freeze
11
11
 
12
12
  profile do
13
13
  10_000.times do
@@ -6,7 +6,7 @@ VALID_INPUT = {
6
6
  name: 'John',
7
7
  age: 20,
8
8
  email: 'john@doe.com'
9
- }
9
+ }.freeze
10
10
 
11
11
  profile do
12
12
  10_000.times do
@@ -1,47 +1,47 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require 'dry/types/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.name = "dry-types"
8
+ spec.name = 'dry-types'
9
9
  spec.version = Dry::Types::VERSION.dup
10
- spec.authors = ["Piotr Solnica"]
11
- spec.email = ["piotr.solnica@gmail.com"]
10
+ spec.authors = ['Piotr Solnica']
11
+ spec.email = ['piotr.solnica@gmail.com']
12
12
  spec.license = 'MIT'
13
13
 
14
14
  spec.summary = 'Type system for Ruby supporting coercions, constraints and complex types like structs, value objects, enums etc.'
15
15
  spec.description = spec.summary
16
- spec.homepage = "https://github.com/dry-rb/dry-types"
16
+ spec.homepage = 'https://github.com/dry-rb/dry-types'
17
17
 
18
18
  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
19
19
  # delete this section to allow pushing this gem to any host.
20
20
  if spec.respond_to?(:metadata)
21
- spec.metadata['allowed_push_host'] = "https://rubygems.org"
22
- spec.metadata['changelog_uri'] = "https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md"
23
- spec.metadata['source_code_uri'] = "https://github.com/dry-rb/dry-types"
24
- spec.metadata['bug_tracker_uri'] = "https://github.com/dry-rb/dry-types/issues"
21
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
22
+ spec.metadata['changelog_uri'] = 'https://github.com/dry-rb/dry-types/blob/master/CHANGELOG.md'
23
+ spec.metadata['source_code_uri'] = 'https://github.com/dry-rb/dry-types'
24
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/dry-rb/dry-types/issues'
25
25
  else
26
- raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
26
+ raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
27
27
  end
28
28
 
29
29
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - ['bin/console', 'bin/setup']
30
- spec.bindir = "exe"
30
+ spec.bindir = 'exe'
31
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
- spec.require_paths = ["lib"]
33
- spec.required_ruby_version = ">= 2.4.0"
32
+ spec.require_paths = ['lib']
33
+ spec.required_ruby_version = '>= 2.4.0'
34
34
 
35
35
  spec.add_runtime_dependency 'concurrent-ruby', '~> 1.0'
36
- spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
37
- spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
38
36
  spec.add_runtime_dependency 'dry-container', '~> 0.3'
37
+ spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.4'
39
38
  spec.add_runtime_dependency 'dry-equalizer', '~> 0.2', '>= 0.2.2'
40
- spec.add_runtime_dependency 'dry-logic', '~> 1.0'
39
+ spec.add_runtime_dependency 'dry-inflector', '~> 0.1', '>= 0.1.2'
40
+ spec.add_runtime_dependency 'dry-logic', '~> 1.0', '>= 1.0.2'
41
41
 
42
- spec.add_development_dependency "bundler"
43
- spec.add_development_dependency "rake", "~> 11.0"
44
- spec.add_development_dependency "rspec", "~> 3.3"
42
+ spec.add_development_dependency 'bundler'
45
43
  spec.add_development_dependency 'dry-monads', '~> 0.2'
44
+ spec.add_development_dependency 'rake', '~> 11.0'
45
+ spec.add_development_dependency 'rspec', '~> 3.3'
46
46
  spec.add_development_dependency 'yard', '~> 0.9.5'
47
47
  end
@@ -33,7 +33,7 @@ module Dry
33
33
  extend Dry::Core::Deprecations[:'dry-types']
34
34
  include Dry::Core::Constants
35
35
 
36
- TYPE_SPEC_REGEX = %r[(.+)<(.+)>].freeze
36
+ TYPE_SPEC_REGEX = /(.+)<(.+)>/.freeze
37
37
 
38
38
  # @see Dry.Types
39
39
  def self.module(*namespaces, default: :nominal, **aliases)
@@ -45,7 +45,7 @@ module Dry
45
45
 
46
46
  # @api private
47
47
  def self.included(*)
48
- raise RuntimeError, "Import Dry.Types, not Dry::Types"
48
+ raise 'Import Dry.Types, not Dry::Types'
49
49
  end
50
50
 
51
51
  # Return container with registered built-in type objects
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dry/types/array/member'
4
+ require 'dry/types/array/constructor'
4
5
 
5
6
  module Dry
6
7
  module Types
@@ -24,6 +25,11 @@ module Dry
24
25
 
25
26
  Array::Member.new(primitive, **options, member: member)
26
27
  end
28
+
29
+ # @api private
30
+ def constructor_type
31
+ ::Dry::Types::Array::Constructor
32
+ end
27
33
  end
28
34
  end
29
35
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/types/constructor'
4
+
5
+ module Dry
6
+ module Types
7
+ # @api public
8
+ class Array < Nominal
9
+ # @api private
10
+ class Constructor < ::Dry::Types::Constructor
11
+ # @api private
12
+ def constructor_type
13
+ ::Dry::Types::Array::Constructor
14
+ end
15
+
16
+ # @return [Lax]
17
+ #
18
+ # @api public
19
+ def lax
20
+ Lax.new(type.lax.constructor(fn, meta: meta))
21
+ end
22
+
23
+ # @see Dry::Types::Array#of
24
+ #
25
+ # @api public
26
+ def of(member)
27
+ type.of(member).constructor(fn, meta: meta)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'dry/types/array/constructor'
4
+
3
5
  module Dry
4
6
  module Types
5
7
  class Array < Nominal
@@ -111,6 +113,11 @@ module Dry
111
113
  [:array, [member, meta ? self.meta : EMPTY_HASH]]
112
114
  end
113
115
  end
116
+
117
+ # @api private
118
+ def constructor_type
119
+ ::Dry::Types::Array::Constructor
120
+ end
114
121
  end
115
122
  end
116
123
  end
@@ -75,7 +75,7 @@ module Dry
75
75
  ' Be careful: types will return the same instance of the default'\
76
76
  ' value every time. Call `.freeze` when setting the default'\
77
77
  ' or pass `shared: true` to discard this warning.'\
78
- "\n#{ where }",
78
+ "\n#{where}",
79
79
  tag: :'dry-types'
80
80
  )
81
81
  end
@@ -108,21 +108,21 @@ module Dry
108
108
  Types['nominal.hash'].map(key_type, value_type)
109
109
  end
110
110
 
111
- # # Builds a constrained nominal type accepting any value that
112
- # # responds to given methods
113
- # #
114
- # # @example
115
- # # Types::Callable = Types.Contract(:call)
116
- # # Types::Contact = Types.Contract(:name, :address)
117
- # #
118
- # # @param methods [Array<String, Symbol>] Method names
119
- # #
120
- # # @return [Dry::Types::Contrained]
121
- # def Contract(*methods)
122
- # methods.reduce(Types['nominal.any']) do |type, method|
123
- # type.constrained(respond_to: method)
124
- # end
125
- # end
111
+ # Builds a constrained nominal type accepting any value that
112
+ # responds to given methods
113
+ #
114
+ # @example
115
+ # Types::Callable = Types.Interface(:call)
116
+ # Types::Contact = Types.Interface(:name, :address)
117
+ #
118
+ # @param methods [Array<String, Symbol>] Method names
119
+ #
120
+ # @return [Dry::Types::Contrained]
121
+ def Interface(*methods)
122
+ methods.reduce(Types['nominal.any']) do |type, method|
123
+ type.constrained(respond_to: method)
124
+ end
125
+ end
126
126
  end
127
127
  end
128
128
  end
@@ -36,8 +36,8 @@ module Dry
36
36
  if input.respond_to?(:to_str)
37
37
  begin
38
38
  ::Date.parse(input)
39
- rescue ArgumentError, RangeError => error
40
- CoercionError.handle(error, &block)
39
+ rescue ArgumentError, RangeError => e
40
+ CoercionError.handle(e, &block)
41
41
  end
42
42
  elsif block_given?
43
43
  yield
@@ -57,8 +57,8 @@ module Dry
57
57
  if input.respond_to?(:to_str)
58
58
  begin
59
59
  ::DateTime.parse(input)
60
- rescue ArgumentError => error
61
- CoercionError.handle(error, &block)
60
+ rescue ArgumentError => e
61
+ CoercionError.handle(e, &block)
62
62
  end
63
63
  elsif block_given?
64
64
  yield
@@ -78,8 +78,8 @@ module Dry
78
78
  if input.respond_to?(:to_str)
79
79
  begin
80
80
  ::Time.parse(input)
81
- rescue ArgumentError => error
82
- CoercionError.handle(error, &block)
81
+ rescue ArgumentError => e
82
+ CoercionError.handle(e, &block)
83
83
  end
84
84
  elsif block_given?
85
85
  yield
@@ -88,6 +88,19 @@ module Dry
88
88
  end
89
89
  end
90
90
 
91
+ # @param [#to_sym, Object] input
92
+ #
93
+ # @return [Symbol, Object]
94
+ #
95
+ # @raise CoercionError
96
+ #
97
+ # @api public
98
+ def to_symbol(input, &block)
99
+ input.to_sym
100
+ rescue NoMethodError => e
101
+ CoercionError.handle(e, &block)
102
+ end
103
+
91
104
  private
92
105
 
93
106
  # Checks whether String is empty