dry-struct 0.7.0 → 1.0.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: 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.