dry-struct 0.7.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ea6fc5c14bec80d877a1a04549fa897c48fb6d028e9a35c86f05d59fff4cf65
4
- data.tar.gz: 38062528ba03fb91e4d0c4ca95dc526e1db4703a71b0095a5d99d43b1112a015
3
+ metadata.gz: b8e3499eadacef74b5203366275c7f68c77ad138e950ac4e5f0a02635bc118f9
4
+ data.tar.gz: a227f8eb3d8beb3b1388bbe1d447055076938611929ed0a41610253feae64741
5
5
  SHA512:
6
- metadata.gz: d29117cb09adefbdca14a7ed0ce5ed3e0b3cf22d5167ae30ab143bad0771c0d02782f0386f3995a4aa1625303a759894473ddc668e67d4a04bd93a818458bdc2
7
- data.tar.gz: 5e1f4cdba2ceb5325c90fa454701daac5d82b410a4b6742eda3bfb467038aee16fd5796a8d0819cc8c510471590ffc42fb9fe3f4b04e9f3bf11d359b8b850a4d
6
+ metadata.gz: 1c721723926e9edaf876e0e96e209fbdd33b882a9f92b2b670aeb3af26901c9c42d262a7446e811706c4fe02a3eb4bf76895747c2cac084ad20023952f480879
7
+ data.tar.gz: a0dba3a720335d985feea9004a0b1ec1f8bb8625a4b6947a22acb6ab68bb0f4fb23aea38c8122570475ed332dc408330391d1572707216007f302e853e8a6e66
@@ -8,9 +8,9 @@ after_success:
8
8
  - '[ -d coverage ] && bundle exec codeclimate-test-reporter'
9
9
  rvm:
10
10
  - 2.4.5
11
- - 2.5.3
12
- - 2.6.1
13
- - jruby-9.2.6.0
11
+ - 2.5.5
12
+ - 2.6.3
13
+ - jruby-9.2.7.0
14
14
  - truffleruby
15
15
  env:
16
16
  global:
@@ -1,3 +1,20 @@
1
+ # 1.0.0 2019-04-23
2
+
3
+ ## Changed
4
+
5
+ * `valid?` and `===` behave differently, `===` works the same way `Class#===` does and `valid?` checks if the value _can be_ coerced to the struct (flash-gordon)
6
+
7
+ ## Added
8
+
9
+ * `Struct.call` now accepts an optional block that will be called on failed coercion. This behavior is consistent with dry-types 1.0. Note that `.new` doesn't take a block (flash-gordon)
10
+ ```ruby
11
+ User = Dry::Struct(name: 'string')
12
+ User.(1) { :oh_no }
13
+ # => :oh_no
14
+ ```
15
+
16
+ [Compare v0.7.0...v1.0.0](https://github.com/dry-rb/dry-struct/compare/v0.7.0...v1.0.0)
17
+
1
18
  # 0.7.0 2019-03-22
2
19
 
3
20
  ## Changed
data/Gemfile CHANGED
@@ -7,7 +7,7 @@ gemspec
7
7
  group :test do
8
8
  gem 'codeclimate-test-reporter', platform: :mri, require: false
9
9
  gem 'simplecov', require: false
10
- gem 'warning' if RUBY_VERSION >= '2.4.0'
10
+ gem 'warning'
11
11
  end
12
12
 
13
13
  group :tools do
@@ -22,4 +22,5 @@ group :benchmarks do
22
22
  gem 'virtus'
23
23
  gem 'fast_attributes'
24
24
  gem 'attrio'
25
+ gem 'hotch'
25
26
  end
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  [gem]: https://rubygems.org/gems/dry-struct
2
2
  [travis]: https://travis-ci.org/dry-rb/dry-struct
3
3
  [codeclimate]: https://codeclimate.com/github/dry-rb/dry-struct
4
- [coveralls]: https://coveralls.io/r/dry-rb/dry-struct
5
4
  [inchpages]: http://inch-ci.org/github/dry-rb/dry-struct
5
+ [chat]: https://dry-rb.zulipchat.com
6
6
 
7
- # dry-struct [![Join the chat at https://gitter.im/dry-rb/chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dry-rb/chat)
7
+ # dry-struct [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/dry-struct.svg)][gem]
10
10
  [![Build Status](https://travis-ci.org/dry-rb/dry-struct.svg?branch=master)][travis]
@@ -42,7 +42,7 @@ class AttrioUser
42
42
  end
43
43
 
44
44
  class DryStructUser < Dry::Struct
45
- attributes(name: 'string', age: 'form.int')
45
+ attributes(name: 'strict.string', age: 'params.integer')
46
46
  end
47
47
 
48
48
  puts DryStructUser.new(name: 'Jane', age: '21').inspect
@@ -21,9 +21,9 @@ module Types
21
21
  end
22
22
 
23
23
  class DryStructUser < Dry::Struct
24
- attribute :id, Types::Form::Int
24
+ attribute :id, Types::Params::Integer
25
25
  attribute :name, Types::Strict::String.constrained(size: 3..64)
26
- attribute :age, Types::Form::Int.constrained(gt: 18)
26
+ attribute :age, Types::Params::Integer.constrained(gt: 18)
27
27
  end
28
28
 
29
29
  puts ARUser.new(id: 1, name: 'Jane', age: '21').inspect
@@ -0,0 +1,19 @@
1
+ require_relative 'setup'
2
+
3
+ ATTR_NAMES = [:attr0, :attr1, :attr2, :attr3, :attr4, :attr5, :attr6, :attr7, :attr8, :attr9]
4
+
5
+ class Integers < Dry::Struct
6
+ ATTR_NAMES.each do |name|
7
+ attribute? name, 'coercible.integer'
8
+ end
9
+ end
10
+
11
+ integers = {attr0: 0, attr1: 1, attr2: 2, attr3: 3, attr4: 4, attr5: 5, attr6: 6, attr7: 7, attr8: 8, attr9: 9}
12
+
13
+ require 'pry-byebug'
14
+
15
+ profile do
16
+ 1_000_000.times do
17
+ Integers.new(integers)
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/ips'
4
+ require 'hotch'
5
+ ENV['HOTCH_VIEWER'] ||= 'open'
6
+
7
+ require 'dry-struct'
8
+
9
+ def profile(&block)
10
+ Hotch(filter: 'Dry', &block)
11
+ end
@@ -27,10 +27,10 @@ Gem::Specification.new do |spec|
27
27
  spec.bindir = 'exe'
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
- spec.required_ruby_version = ">= 2.3.0"
30
+ spec.required_ruby_version = ">= 2.4.0"
31
31
 
32
32
  spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
33
- spec.add_runtime_dependency 'dry-types', '~> 0.15'
33
+ spec.add_runtime_dependency 'dry-types', '~> 1.0'
34
34
  spec.add_runtime_dependency 'dry-core', '~> 0.4', '>= 0.4.3'
35
35
  spec.add_runtime_dependency 'ice_nine', '~> 0.11'
36
36
 
@@ -188,3 +188,4 @@ end
188
188
 
189
189
  require 'dry/struct/value'
190
190
  require 'dry/struct/extensions'
191
+ require 'dry/struct/printer'
@@ -63,8 +63,8 @@ module Dry
63
63
  # @example with a nested array of structs
64
64
  # class Language < Dry::Struct
65
65
  # attribute :name, Types::String
66
- # array :versions, Types::String
67
- # array :celebrities, Types::Array.of(Dry::Struct) do
66
+ # attribute :versions, Types::Array.of(Types::String)
67
+ # attribute :celebrities, Types::Array.of(Dry::Struct) do
68
68
  # attribute :name, Types::String
69
69
  # attribute :pseudonym, Types::String
70
70
  # end
@@ -157,8 +157,8 @@ module Dry
157
157
  keys.each do |key|
158
158
  next if instance_methods.include?(key)
159
159
  class_eval(<<-RUBY)
160
- def #{ key }
161
- @attributes[#{ key.inspect }]
160
+ def #{key}
161
+ @attributes[#{key.inspect}]
162
162
  end
163
163
  RUBY
164
164
  end
@@ -222,16 +222,36 @@ module Dry
222
222
 
223
223
  # @param [Hash{Symbol => Object},Dry::Struct] attributes
224
224
  # @raise [Struct::Error] if the given attributes don't conform {#schema}
225
- def new(attributes = default_attributes)
226
- if attributes.instance_of?(self)
225
+ def new(attributes = default_attributes, safe = false)
226
+ if equal?(attributes.class)
227
227
  attributes
228
+ elsif safe
229
+ load(schema.call_safe(attributes) { |output = attributes| return yield output })
228
230
  else
229
- super(schema[attributes])
231
+ load(schema.call_unsafe(attributes))
230
232
  end
231
- rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => error
233
+ rescue Types::CoercionError => error
232
234
  raise Struct::Error, "[#{self}.new] #{error}"
233
235
  end
234
236
 
237
+ # @api private
238
+ def call_safe(input, &block)
239
+ if input.is_a?(self)
240
+ input
241
+ else
242
+ new(input, true, &block)
243
+ end
244
+ end
245
+
246
+ # @api private
247
+ def call_unsafe(input)
248
+ if input.is_a?(self)
249
+ input
250
+ else
251
+ new(input)
252
+ end
253
+ end
254
+
235
255
  # @api private
236
256
  def load(attributes)
237
257
  struct = allocate
@@ -239,17 +259,6 @@ module Dry
239
259
  struct
240
260
  end
241
261
 
242
- # Calls type constructor. The behavior is identical to `.new` but returns
243
- # the input back if it's a subclass of the struct.
244
- #
245
- # @param [Hash{Symbol => Object},Dry::Struct] attributes
246
- # @return [Dry::Struct]
247
- def call(attributes = default_attributes)
248
- return attributes if attributes.is_a?(self)
249
- new(attributes)
250
- end
251
- alias_method :[], :call
252
-
253
262
  # @param [#call,nil] constructor
254
263
  # @param [Hash] _options
255
264
  # @param [#call,nil] block
@@ -274,7 +283,7 @@ module Dry
274
283
  # @private
275
284
  def try_struct(input)
276
285
  if input.is_a?(self)
277
- Types::Result::Success.new(input)
286
+ input
278
287
  else
279
288
  yield
280
289
  end
@@ -305,9 +314,10 @@ module Dry
305
314
 
306
315
  # @param [Object, Dry::Struct] value
307
316
  # @return [Boolean]
308
- def valid?(value)
309
- self === value
317
+ def ===(other)
318
+ other.is_a?(self)
310
319
  end
320
+ alias_method :primitive?, :===
311
321
 
312
322
  # @return [true]
313
323
  def constrained?
@@ -324,6 +334,11 @@ module Dry
324
334
  false
325
335
  end
326
336
 
337
+ # @return [Proc]
338
+ def to_proc
339
+ proc { |input| call(input) }
340
+ end
341
+
327
342
  # Checks if this {Struct} has the given attribute
328
343
  #
329
344
  # @param [Symbol] key Attribute name
@@ -0,0 +1,18 @@
1
+ require 'dry/types/printer'
2
+
3
+ module Dry
4
+ module Types
5
+ # @api private
6
+ class Printer
7
+ MAPPING[Struct::Sum] = :visit_struct_sum
8
+
9
+ def visit_struct_sum(sum)
10
+ visit_sum_constructors(sum) do |constructors|
11
+ visit_options(EMPTY_HASH, sum.meta) do |opts|
12
+ yield "Struct::Sum<#{constructors}#{opts}>"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,5 @@
1
1
  require 'dry/types/sum'
2
+ require 'dry/types/printer'
2
3
 
3
4
  module Dry
4
5
  class Struct
@@ -6,6 +7,11 @@ module Dry
6
7
  # As opposed to Dry::Types::Sum::Constrained
7
8
  # this type tries no to coerce data first.
8
9
  class Sum < Dry::Types::Sum::Constrained
10
+ def call(input)
11
+ left.try_struct(input) do
12
+ right.try_struct(input) { super }
13
+ end
14
+ end
9
15
  # @param [Hash{Symbol => Object},Dry::Struct] input
10
16
  # @yieldparam [Dry::Types::Result::Failure] failure
11
17
  # @yieldreturn [Dry::Types::ResultResult]
@@ -23,12 +29,17 @@ module Dry
23
29
  # @return [Dry::Types::Sum]
24
30
  def |(type)
25
31
  if type.is_a?(Class) && type <= Struct || type.is_a?(Sum)
26
- self.class.new(self, type)
32
+ Sum.new(self, type)
27
33
  else
28
34
  super
29
35
  end
30
36
  end
31
37
 
38
+ # @return [boolean]
39
+ def ===(value)
40
+ left === value || right === value
41
+ end
42
+
32
43
  protected
33
44
 
34
45
  # @private
@@ -1,6 +1,6 @@
1
1
  module Dry
2
2
  class Struct
3
3
  # @private
4
- VERSION = '0.7.0'.freeze
4
+ VERSION = '1.0.0'.freeze
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-22 00:00:00.000000000 Z
11
+ date: 2019-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dry-equalizer
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.15'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.15'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: dry-core
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -147,6 +147,8 @@ files:
147
147
  - Rakefile
148
148
  - benchmarks/basic.rb
149
149
  - benchmarks/constrained.rb
150
+ - benchmarks/profile_instantiation.rb
151
+ - benchmarks/setup.rb
150
152
  - bin/console
151
153
  - bin/setup
152
154
  - dry-struct.gemspec
@@ -158,6 +160,7 @@ files:
158
160
  - lib/dry/struct/extensions.rb
159
161
  - lib/dry/struct/extensions/pretty_print.rb
160
162
  - lib/dry/struct/hashify.rb
163
+ - lib/dry/struct/printer.rb
161
164
  - lib/dry/struct/struct_builder.rb
162
165
  - lib/dry/struct/sum.rb
163
166
  - lib/dry/struct/value.rb
@@ -178,14 +181,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
178
181
  requirements:
179
182
  - - ">="
180
183
  - !ruby/object:Gem::Version
181
- version: 2.3.0
184
+ version: 2.4.0
182
185
  required_rubygems_version: !ruby/object:Gem::Requirement
183
186
  requirements:
184
187
  - - ">="
185
188
  - !ruby/object:Gem::Version
186
189
  version: '0'
187
190
  requirements: []
188
- rubygems_version: 3.0.1
191
+ rubygems_version: 3.0.3
189
192
  signing_key:
190
193
  specification_version: 4
191
194
  summary: Typed structs and value objects.