dry-struct 1.6.0 → 1.8.1

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: f3309e15a4b8084a8ddb210a4d62e51e063a54f0aec56f41398f41824bbfe687
4
- data.tar.gz: 05de1a1085a1753cd22f6f42a459de2245a544fe6ab822dff2bae228fe91da45
3
+ metadata.gz: b3949661d29cee88a8d29876846e0f6dd4e092f2f65a43307cfaa38814bf8f8b
4
+ data.tar.gz: ec23916ce98b47fecd001b958620e190fed5688a929b002f4cc048620a3df999
5
5
  SHA512:
6
- metadata.gz: 16f8476d1362fa11871db6be02787e8b106795ca5d4a1ebeb1c796cc22abcd5ee0c0cf8f7985191a180dcfb38a1679535be4ff13003e0b08459072a2b236e288
7
- data.tar.gz: e8973dbc9cc1fc0033751299ac366504c047cd996e9e9c5718ecad6e2d4bf2cdb734d46fd76f99c074a7982cb8cff6f9085a18725a01b21ea6e42475218f06e5
6
+ metadata.gz: 5458cb033a707cce2d4058b71ed81ec791d3ecfe98b4c8f9520b9297453c31df7fd2f658b1083230288761279053db0b2fd5db3481f8fa450ff1a2d8a29e6783
7
+ data.tar.gz: 449f59b1cb3954d815c8ba7191e148e05ac8d594cc89f56e7673bcca9922e7ab5cdc447e6a591a3154993ea81298cf0ec3d9c7a330c5bd1979395f96118d97a1
data/CHANGELOG.md CHANGED
@@ -1,45 +1,138 @@
1
- <!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
1
+ # Changelog
2
2
 
3
- ## 1.6.0 2022-11-04
3
+ All notable changes to this project will be documented in this file.
4
4
 
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Break Versioning](https://www.taoensso.com/break-versioning).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
5
11
 
6
12
  ### Changed
7
13
 
8
- - This version uses dry-core 1.0 (@flash-gordon + @solnic)
14
+ ### Deprecated
15
+
16
+ ### Removed
17
+
18
+ ### Fixed
19
+
20
+ ### Security
21
+
22
+ [Unreleased]: https://github.com/dry-rb/dry-struct/compare/v1.8.1...main
23
+
24
+ ## [1.8.1] - 2026-03-03
25
+
26
+ ### Changed
27
+
28
+ - Performance improvements for building a hash from `Dry::Struct` when it contains nested structs. (@katafrakt in #202, identified by @rpeng in #200)
29
+
30
+ [1.8.1]: https://github.com/dry-rb/dry-struct/compare/v1.8.0...v1.8.1
31
+
32
+ ## [1.8.0] - 2025-03-09
33
+
34
+ ### Added
35
+
36
+ - Added super_diff extension for improved struct diffing in RSpec tests (@flash-gordon in #197)
37
+
38
+ Add this to your Gemfile:
39
+ ```ruby
40
+ gem 'super_diff', group: :test
41
+ ```
42
+
43
+ Then activate the extension in your spec_helper:
44
+ ```ruby
45
+ Dry::Struct.load_extensions(:super_diff)
46
+ ```
47
+
48
+ Now this
49
+
50
+ ```ruby
51
+ expected: #<Test::User name="Jane" age=22>
52
+ got: #<Test::User name="Jane" age=21>
53
+
54
+ (compared using eql?)
55
+
56
+ Diff:
57
+ @@ -1 +1 @@
58
+ -#<Test::User name="Jane" age=22>
59
+ +#<Test::User name="Jane" age=21>
60
+ ```
9
61
 
10
- [Compare v1.5.2...v1.6.0](https://github.com/dry-rb/dry-struct/compare/v1.5.2...v1.6.0)
62
+ will become this:
11
63
 
12
- ## 1.5.2 2022-10-19
64
+ ```ruby
65
+ expected: #<Test::User name: "Jane", age: 22>
66
+ got: #<Test::User name: "Jane", age: 21>
67
+
68
+ (compared using eql?)
69
+
70
+ #<Test::User {
71
+ name: "Jane",
72
+ - age: 22
73
+ + age: 21
74
+ }>
75
+ ```
76
+
77
+ [1.8.0]: https://github.com/dry-rb/dry-struct/compare/v1.7.1...v1.8.0
13
78
 
79
+ ## [1.7.1] - 2025-01-31
14
80
 
15
81
  ### Fixed
16
82
 
17
- - Coercion failures keep the original error instead of just having a string (@flash-gordon + @newx)
83
+ - Syntax errors on 3.3.0 (@flash-gordon, see https://github.com/dry-rb/dry-types/issues/478)
84
+
85
+ [1.7.1]: https://github.com/dry-rb/dry-struct/compare/v1.7.0...v1.7.1
18
86
 
87
+ ## [1.7.0] - 2025-01-06
19
88
 
20
- [Compare v1.5.1...v1.5.2](https://github.com/dry-rb/dry-struct/compare/v1.5.1...v1.5.2)
89
+ ### Fixed
21
90
 
22
- ## 1.5.1 2022-10-17
91
+ - Fixed coercion errors for structs (issue #192 via #193) (@flash-gordon)
92
+ - Invalid method names are now allowed as struct attributes (issue #169 via #195) (@flash-gordon)
93
+
94
+ ### Changed
23
95
 
96
+ - Missing attribute error now includes the name of the class (issue #170 via #191) (@phillipoertel + @cllns)
97
+ - 3.1 is now the minimum Ruby version (@flash-gordon)
98
+ - `Dry::Struct::Error` is now a subclass of `Dry::Types::CoercionError` (in #193) (@flash-gordon)
99
+ - `Dry::Struct#[]` now returns `nil` if an optional attribute is not set. This is consistent with calling accessor methods for optional attributes. (issue #171 via #194) (@ivleonov + @flash-gordon)
100
+
101
+ [1.7.0]: https://github.com/dry-rb/dry-struct/compare/v1.6.0...v1.7.0
102
+
103
+ ## [1.6.0] - 2022-11-04
104
+
105
+ ### Changed
106
+
107
+ - This version uses dry-core 1.0 (@flash-gordon + @solnic)
108
+
109
+ [1.6.0]: https://github.com/dry-rb/dry-struct/compare/v1.5.2...v1.6.0
110
+
111
+ ## [1.5.2] - 2022-10-19
24
112
 
25
113
  ### Fixed
26
114
 
27
- - Fixed issues with auto-loading `Extensions` module (issue #183 fixed via #184) (@solnic)
115
+ - Coercion failures keep the original error instead of just having a string (@flash-gordon + @newx)
28
116
 
117
+ [1.5.2]: https://github.com/dry-rb/dry-struct/compare/v1.5.1...v1.5.2
29
118
 
30
- [Compare v1.5.0...v1.5.1](https://github.com/dry-rb/dry-struct/compare/v1.5.0...v1.5.1)
119
+ ## [1.5.1] - 2022-10-17
31
120
 
32
- ## 1.5.0 2022-10-15
121
+ ### Fixed
122
+
123
+ - Fixed issues with auto-loading `Extensions` module (issue #183 fixed via #184) (@solnic)
33
124
 
125
+ [1.5.1]: https://github.com/dry-rb/dry-struct/compare/v1.5.0...v1.5.1
126
+
127
+ ## [1.5.0] - 2022-10-15
34
128
 
35
129
  ### Changed
36
130
 
37
131
  - Use zeitwerk for auto-loading (@flash-gordon)
38
132
 
39
- [Compare v1.4.0...v1.5.0](https://github.com/dry-rb/dry-struct/compare/v1.4.0...v1.5.0)
40
-
41
- ## 1.4.0 2021-01-21
133
+ [1.5.0]: https://github.com/dry-rb/dry-struct/compare/v1.4.0...v1.5.0
42
134
 
135
+ ## [1.4.0] - 2021-01-21
43
136
 
44
137
  ### Added
45
138
 
@@ -56,11 +149,9 @@
56
149
  User.new(name: "John", address: nil) # => #<User name="John" address=nil>
57
150
  ```
58
151
 
152
+ [1.4.0]: https://github.com/dry-rb/dry-struct/compare/v1.3.0...v1.4.0
59
153
 
60
- [Compare v1.3.0...v1.4.0](https://github.com/dry-rb/dry-struct/compare/v1.3.0...v1.4.0)
61
-
62
- ## 1.3.0 2020-02-10
63
-
154
+ ## [1.3.0] - 2020-02-10
64
155
 
65
156
  ### Added
66
157
 
@@ -110,20 +201,18 @@
110
201
 
111
202
  - [internal] metadata is now stored inside schema (@flash-gordon)
112
203
 
113
- [Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-struct/compare/v1.2.0...v1.3.0)
114
-
115
- ## 1.2.0 2019-12-20
204
+ [1.3.0]: https://github.com/dry-rb/dry-struct/compare/v1.2.0...v1.3.0
116
205
 
206
+ ## [1.2.0] - 2019-12-20
117
207
 
118
208
  ### Changed
119
209
 
120
210
  - `Dry::Struct::Value` is deprecated. `Dry::Struct` instances were never meant to be mutable, we have no support for this. The only difference between `Dry::Struct` and `Dry::Struct::Value` is that the latter is deeply frozen. Freezing objects slows the code down and gives you very little benefit in return. If you have a use case for `Value`, it won't be hard to roll your own solution using [ice_nine](https://github.com/dkubb/ice_nine) (flash-gordon)
121
211
  - In the thread of the previous change, structs now use immutable equalizer. This means `Struct#hash` memoizes its value after the first invocation. Depending on the case, this may speed up your code significantly (flash-gordon)
122
212
 
123
- [Compare v1.1.1...v1.2.0](https://github.com/dry-rb/dry-struct/compare/v1.1.1...v1.2.0)
124
-
125
- ## 1.1.1 2019-10-13
213
+ [1.2.0]: https://github.com/dry-rb/dry-struct/compare/v1.1.1...v1.2.0
126
214
 
215
+ ## [1.1.1] - 2019-10-13
127
216
 
128
217
  ### Changed
129
218
 
@@ -144,20 +233,17 @@
144
233
 
145
234
  See more examples in the [specs](https://github.com/dry-rb/dry-struct/blob/8112772eb08d22ff2cd3e6997514d79a9b124968/spec/dry/struct/pattern_matching_spec.rb).
146
235
 
147
- [Compare v1.1.0...v1.1.1](https://github.com/dry-rb/dry-struct/compare/v1.1.0...v1.1.1)
148
-
149
- ## 1.1.0 2019-10-07
236
+ [1.1.1]: https://github.com/dry-rb/dry-struct/compare/v1.1.0...v1.1.1
150
237
 
238
+ ## [1.1.0] - 2019-10-07
151
239
 
152
240
  ### Added
153
241
 
154
242
  - Experimental support for pattern matching :tada: (flash-gordon)
155
243
 
244
+ [1.1.0]: https://github.com/dry-rb/dry-struct/compare/v1.0.0...v1.1.0
156
245
 
157
- [Compare v1.0.0...v1.1.0](https://github.com/dry-rb/dry-struct/compare/v1.0.0...v1.1.0)
158
-
159
- ## 1.0.0 2019-04-23
160
-
246
+ ## [1.0.0] - 2019-04-23
161
247
 
162
248
  ### Added
163
249
 
@@ -172,10 +258,9 @@
172
258
 
173
259
  - `valid?` and `===` behave differently, `===` works the same way `Class#===` does and `valid?` checks if the value _can be_ coerced to the struct (flash-gordon)
174
260
 
175
- [Compare v0.7.0...v1.0.0](https://github.com/dry-rb/dry-struct/compare/v0.7.0...v1.0.0)
176
-
177
- ## 0.7.0 2019-03-22
261
+ [1.0.0]: https://github.com/dry-rb/dry-struct/compare/v0.7.0...v1.0.0
178
262
 
263
+ ## [0.7.0] - 2019-03-22
179
264
 
180
265
  ### Changed
181
266
 
@@ -202,10 +287,9 @@
202
287
  - `Dry::Stuct#new` is now more efficient for partial updates (flash-gordon)
203
288
  - Ruby 2.3 is EOL and not officially supported. It may work but we don't test it.
204
289
 
205
- [Compare v0.6.0...v0.7.0](https://github.com/dry-rb/dry-struct/compare/v0.6.0...v0.7.0)
206
-
207
- ## 0.6.0 2018-10-24
290
+ [0.7.0]: https://github.com/dry-rb/dry-struct/compare/v0.6.0...v0.7.0
208
291
 
292
+ ## [0.6.0] - 2018-10-24
209
293
 
210
294
  ### Added
211
295
 
@@ -227,10 +311,9 @@
227
311
 
228
312
  - [BREAKING] `Struct.attribute?` in the old sense is deprecated, use `has_attribute?` as a replacement
229
313
 
230
- [Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-struct/compare/v0.5.1...v0.6.0)
231
-
232
- ## 0.5.1 2018-08-11
314
+ [0.6.0]: https://github.com/dry-rb/dry-struct/compare/v0.5.1...v0.6.0
233
315
 
316
+ ## [0.5.1] - 2018-08-11
234
317
 
235
318
  ### Added
236
319
 
@@ -248,11 +331,9 @@
248
331
 
249
332
  - Constant resolution is now restricted to the current module when structs are automatically defined using the block syntax. This shouldn't break any existing code (piktur)
250
333
 
334
+ [0.5.1]: https://github.com/dry-rb/dry-struct/compare/v0.5.0...v0.5.1
251
335
 
252
- [Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-struct/compare/v0.5.0...v0.5.1)
253
-
254
- ## 0.5.0 2018-05-03
255
-
336
+ ## [0.5.0] - 2018-05-03
256
337
 
257
338
  ### Added
258
339
 
@@ -309,11 +390,9 @@
309
390
  - Adding a new attribute invalidates `attribute_names` (flash-gordon)
310
391
  - Struct classes track subclasses and define attributes in them, now it doesn't matter whether you define attributes first and _then_ subclass or vice versa. Note this can lead to memory leaks in Rails environment when struct classes are reloaded (flash-gordon)
311
392
 
393
+ [0.5.0]: https://github.com/dry-rb/dry-struct/compare/v0.4.0...v0.5.0
312
394
 
313
- [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-struct/compare/v0.4.0...v0.5.0)
314
-
315
- ## 0.4.0 2017-11-04
316
-
395
+ ## [0.4.0] - 2017-11-04
317
396
 
318
397
  ### Fixed
319
398
 
@@ -325,10 +404,9 @@
325
404
  - `Struct#new` uses raw attributes instead of method calls, this makes the behavior consistent with the change above (flash-gordon)
326
405
  - `constructor_type` now actively rejects `:weak` and `:symbolized` values (GustavoCaso)
327
406
 
328
- [Compare v0.3.1...v0.4.0](https://github.com/dry-rb/dry-struct/compare/v0.3.1...v0.4.0)
329
-
330
- ## 0.3.1 2017-06-30
407
+ [0.4.0]: https://github.com/dry-rb/dry-struct/compare/v0.3.1...v0.4.0
331
408
 
409
+ ## [0.3.1] - 2017-06-30
332
410
 
333
411
  ### Added
334
412
 
@@ -336,11 +414,9 @@
336
414
  - `Struct.attribute?` and `Struct.attribute_names` for introspecting struct attributes (flash-gordon)
337
415
  - `Struct#__new__` is a safe-to-use-in-gems alias for `Struct#new` (flash-gordon)
338
416
 
417
+ [0.3.1]: https://github.com/dry-rb/dry-struct/compare/v0.3.0...v0.3.1
339
418
 
340
- [Compare v0.3.0...v0.3.1](https://github.com/dry-rb/dry-struct/compare/v0.3.0...v0.3.1)
341
-
342
- ## 0.3.0 2017-05-05
343
-
419
+ ## [0.3.0] - 2017-05-05
344
420
 
345
421
  ### Added
346
422
 
@@ -355,39 +431,33 @@
355
431
 
356
432
  - `.new` without arguments doesn't use nil as an input for non-default types anymore (flash-gordon)
357
433
 
358
- [Compare v0.2.1...v0.3.0](https://github.com/dry-rb/dry-struct/compare/v0.2.1...v0.3.0)
359
-
360
- ## 0.2.1 2017-02-27
434
+ [0.3.0]: https://github.com/dry-rb/dry-struct/compare/v0.2.1...v0.3.0
361
435
 
436
+ ## [0.2.1] - 2017-02-27
362
437
 
363
438
  ### Fixed
364
439
 
365
440
  - Fixed `Dry::Struct::Value` which appeared to be broken in the last release (flash-gordon)
366
441
 
442
+ [0.2.1]: https://github.com/dry-rb/dry-struct/compare/v0.2.0...v0.2.1
367
443
 
368
- [Compare v0.2.0...v0.2.1](https://github.com/dry-rb/dry-struct/compare/v0.2.0...v0.2.1)
369
-
370
- ## 0.2.0 2016-02-26
371
-
444
+ ## [0.2.0] - 2016-02-26
372
445
 
373
446
  ### Changed
374
447
 
375
448
  - Struct attributes can be overridden in a subclass (flash-gordon)
376
449
 
377
- [Compare v0.1.1...v0.2.0](https://github.com/dry-rb/dry-struct/compare/v0.1.1...v0.2.0)
378
-
379
- ## 0.1.1 2016-11-13
450
+ [0.2.0]: https://github.com/dry-rb/dry-struct/compare/v0.1.1...v0.2.0
380
451
 
452
+ ## [0.1.1] - 2016-11-13
381
453
 
382
454
  ### Fixed
383
455
 
384
456
  - Make `Dry::Struct` act as a constrained type. This fixes the behavior of sum types containing structs (flash-gordon)
385
457
 
458
+ [0.1.1]: https://github.com/dry-rb/dry-struct/compare/v0.1.0...v0.1.1
386
459
 
387
- [Compare v0.1.0...v0.1.1](https://github.com/dry-rb/dry-struct/compare/v0.1.0...v0.1.1)
388
-
389
- ## 0.1.0 2016-09-21
390
-
460
+ ## [0.1.0] - 2016-09-21
391
461
 
392
462
  ### Added
393
463
 
@@ -399,8 +469,10 @@
399
469
  - [BREAKING] `:strict` now raises on unexpected keys (backus)
400
470
  - Structs no longer auto-register themselves in the types container as they implement `Type` interface and we don't have to wrap them in `Type::Definition` (flash-gordon)
401
471
 
402
- [Compare v0.0.1...v0.1.0](https://github.com/dry-rb/dry-struct/compare/v0.0.1...v0.1.0)
472
+ [0.1.0]: https://github.com/dry-rb/dry-struct/compare/v0.0.1...v0.1.0
403
473
 
404
- ## 0.0.1 2016-07-17
474
+ ## [0.0.1] - 2016-07-17
405
475
 
406
476
  Initial release of code imported from dry-types
477
+
478
+ [0.0.1]: https://github.com/dry-rb/dry-struct/releases/tag/v0.0.1
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2022 dry-rb team
3
+ Copyright (c) 2015-2026 Hanakai team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,30 +1,17 @@
1
- <!--- this file is synced from dry-rb/template-gem project -->
2
- [gem]: https://rubygems.org/gems/dry-struct
3
- [actions]: https://github.com/dry-rb/dry-struct/actions
4
- [codacy]: https://www.codacy.com/gh/dry-rb/dry-struct
5
- [chat]: https://dry-rb.zulipchat.com
6
- [inchpages]: http://inch-ci.org/github/dry-rb/dry-struct
1
+ <!--- This file is synced from hanakai-rb/repo-sync -->
7
2
 
8
- # dry-struct [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
3
+ [rubygem]: https://rubygems.org/gems/dry-struct
4
+ [actions]: https://github.com/dry-rb/dry-struct/actions
9
5
 
10
- [![Gem Version](https://badge.fury.io/rb/dry-struct.svg)][gem]
11
- [![CI Status](https://github.com/dry-rb/dry-struct/workflows/ci/badge.svg)][actions]
12
- [![Codacy Badge](https://api.codacy.com/project/badge/Grade/961f5c776f1d49218b2cede3745e059c)][codacy]
13
- [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/961f5c776f1d49218b2cede3745e059c)][codacy]
14
- [![Inline docs](http://inch-ci.org/github/dry-rb/dry-struct.svg?branch=main)][inchpages]
6
+ # dry-struct [![Gem Version](https://badge.fury.io/rb/dry-struct.svg)][rubygem] [![CI Status](https://github.com/dry-rb/dry-struct/workflows/CI/badge.svg)][actions]
15
7
 
16
8
  ## Links
17
9
 
18
- * [User documentation](https://dry-rb.org/gems/dry-struct)
19
- * [API documentation](http://rubydoc.info/gems/dry-struct)
20
-
21
- ## Supported Ruby versions
22
-
23
- This library officially supports the following Ruby versions:
24
-
25
- * MRI `>= 2.7.0`
26
- * jruby `>= 9.3` (postponed until 2.7 is supported)
10
+ - [User documentation](https://dry-rb.org/gems/dry-struct)
11
+ - [API documentation](http://rubydoc.info/gems/dry-struct)
12
+ - [Forum](https://discourse.dry-rb.org)
27
13
 
28
14
  ## License
29
15
 
30
16
  See `LICENSE` file.
17
+
data/dry-struct.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # this file is synced from dry-rb/template-gem project
3
+ # This file is synced from hanakai-rb/repo-sync. To update it, edit repo-sync.yml.
4
4
 
5
5
  lib = File.expand_path("lib", __dir__)
6
6
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -8,8 +8,8 @@ require "dry/struct/version"
8
8
 
9
9
  Gem::Specification.new do |spec|
10
10
  spec.name = "dry-struct"
11
- spec.authors = ["Piotr Solnica"]
12
- spec.email = ["piotr.solnica@gmail.com"]
11
+ spec.authors = ["Hanakai team"]
12
+ spec.email = ["info@hanakai.org"]
13
13
  spec.license = "MIT"
14
14
  spec.version = Dry::Struct::VERSION.dup
15
15
 
@@ -17,25 +17,27 @@ Gem::Specification.new do |spec|
17
17
  spec.description = spec.summary
18
18
  spec.homepage = "https://dry-rb.org/gems/dry-struct"
19
19
  spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-struct.gemspec", "lib/**/*"]
20
- spec.bindir = "bin"
21
- spec.executables = []
20
+ spec.bindir = "exe"
21
+ spec.executables = Dir["exe/*"].map { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
+ spec.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
25
+
24
26
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
25
27
  spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md"
26
28
  spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-struct"
27
29
  spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-struct/issues"
30
+ spec.metadata["funding_uri"] = "https://github.com/sponsors/hanami"
28
31
 
29
- spec.required_ruby_version = ">= 2.7.0"
32
+ spec.required_ruby_version = ">= 3.1.0"
30
33
 
31
- # to update dependencies edit project.yml
32
- spec.add_runtime_dependency "dry-core", "~> 1.0", "< 2"
33
- spec.add_runtime_dependency "dry-types", ">= 1.7", "< 2"
34
- spec.add_runtime_dependency "ice_nine", "~> 0.11"
35
34
  spec.add_runtime_dependency "zeitwerk", "~> 2.6"
36
-
35
+ spec.add_runtime_dependency "dry-core", "~> 1.1"
36
+ spec.add_runtime_dependency "dry-types", "~> 1.8", ">= 1.8.2"
37
+ spec.add_runtime_dependency "ice_nine", "~> 0.11"
37
38
  spec.add_development_dependency "bundler"
38
39
  spec.add_development_dependency "rake"
39
40
  spec.add_development_dependency "rspec"
40
41
  spec.add_development_dependency "yard"
41
42
  end
43
+
@@ -5,21 +5,12 @@ require "weakref"
5
5
  module Dry
6
6
  class Struct
7
7
  # Class-level interface of {Struct} and {Value}
8
- module ClassInterface # rubocop:disable Metrics/ModuleLength
8
+ module ClassInterface
9
9
  include Core::ClassAttributes
10
10
 
11
11
  include Types::Type
12
12
  include Types::Builder
13
13
 
14
- # @param [Class] klass
15
- def inherited(klass)
16
- super
17
-
18
- unless klass.name.eql?("Dry::Struct::Value")
19
- klass.extend(Core::DescendantsTracker)
20
- end
21
- end
22
-
23
14
  # Adds an attribute for this {Struct} with given `name` and `type`
24
15
  # and modifies {.schema} accordingly.
25
16
  #
@@ -92,8 +83,8 @@ module Dry
92
83
  # ruby.celebrities[0].pseudonym #=> 'Matz'
93
84
  # ruby.celebrities[1].name #=> 'Aaron Patterson'
94
85
  # ruby.celebrities[1].pseudonym #=> 'tenderlove'
95
- def attribute(name, type = Undefined, &block)
96
- attributes(name => build_type(name, type, &block))
86
+ def attribute(name, type = Undefined, &)
87
+ attributes(name => build_type(name, type, &))
97
88
  end
98
89
 
99
90
  # Add atributes from another struct
@@ -121,13 +112,13 @@ module Dry
121
112
  #
122
113
  # @param struct [Dry::Struct]
123
114
  def attributes_from(struct)
124
- extracted_schema = struct.schema.keys.map { |key|
115
+ extracted_schema = struct.schema.keys.to_h do |key|
125
116
  if key.required?
126
117
  [key.name, key.type]
127
118
  else
128
119
  [:"#{key.name}?", key.type]
129
120
  end
130
- }.to_h
121
+ end
131
122
  attributes(extracted_schema)
132
123
  end
133
124
 
@@ -145,10 +136,10 @@ module Dry
145
136
  # @param [Dry::Types::Type, nil] type or superclass of nested type
146
137
  # @return [Dry::Struct]
147
138
  #
148
- def attribute?(*args, &block)
149
- if args.size == 1 && block.nil?
139
+ def attribute?(*args, &)
140
+ if args.size == 1 && !block_given?
150
141
  Core::Deprecations.warn(
151
- "Dry::Struct.attribute? is deprecated for checking attribute presence, "\
142
+ "Dry::Struct.attribute? is deprecated for checking attribute presence, " \
152
143
  "use has_attribute? instead",
153
144
  tag: :"dry-struct"
154
145
  )
@@ -157,7 +148,7 @@ module Dry
157
148
  else
158
149
  name, * = args
159
150
 
160
- attribute(:"#{name}?", build_type(*args, &block))
151
+ attribute(:"#{name}?", build_type(*args, &))
161
152
  end
162
153
  end
163
154
 
@@ -189,8 +180,7 @@ module Dry
189
180
 
190
181
  @attribute_names = nil
191
182
 
192
- direct_descendants = descendants.select { |d| d.superclass == self }
193
- direct_descendants.each do |d|
183
+ subclasses.each do |d|
194
184
  inherited_attrs = new_schema.reject { |k, _| d.has_attribute?(k.to_s.chomp("?").to_sym) }
195
185
  d.attributes(inherited_attrs)
196
186
  end
@@ -246,7 +236,7 @@ module Dry
246
236
 
247
237
  # @param [Hash{Symbol => Object},Dry::Struct] attributes
248
238
  # @raise [Struct::Error] if the given attributes don't conform {#schema}
249
- def new(attributes = default_attributes, safe = false, &block) # rubocop:disable Style/OptionalBooleanParameter
239
+ def new(attributes = default_attributes, safe = false, &)
250
240
  if attributes.is_a?(Struct)
251
241
  if equal?(attributes.class)
252
242
  attributes
@@ -256,23 +246,23 @@ module Dry
256
246
  # User.new(super_user)
257
247
  #
258
248
  # We may deprecate this behavior in future forcing people to be explicit
259
- new(attributes.to_h, safe, &block)
249
+ new(attributes.to_h, safe, &)
260
250
  end
261
251
  elsif safe
262
252
  load(schema.call_safe(attributes) { |output = attributes| return yield output })
263
253
  else
264
254
  load(schema.call_unsafe(attributes))
265
255
  end
266
- rescue Types::CoercionError => e
267
- raise Error, "[#{self}.new] #{e}", e.backtrace
256
+ rescue Types::CoercionError => exception
257
+ raise Error, "[#{self}.new] #{exception}", exception.backtrace
268
258
  end
269
259
 
270
260
  # @api private
271
- def call_safe(input, &block)
261
+ def call_safe(input, &)
272
262
  if input.is_a?(self)
273
263
  input
274
264
  else
275
- new(input, true, &block)
265
+ new(input, true, &)
276
266
  end
277
267
  end
278
268
 
@@ -305,8 +295,8 @@ module Dry
305
295
  # @return [Dry::Types::Result]
306
296
  def try(input)
307
297
  success(self[input])
308
- rescue Error => e
309
- failure_result = failure(input, e)
298
+ rescue Error => exception
299
+ failure_result = failure(input, exception)
310
300
  block_given? ? yield(failure_result) : failure_result
311
301
  end
312
302
 
@@ -323,48 +313,32 @@ module Dry
323
313
 
324
314
  # @param [({Symbol => Object})] args
325
315
  # @return [Dry::Types::Result::Success]
326
- def success(*args)
327
- result(Types::Result::Success, *args)
328
- end
316
+ def success(*args) = result(Types::Result::Success, *args)
329
317
 
330
318
  # @param [({Symbol => Object})] args
331
319
  # @return [Dry::Types::Result::Failure]
332
- def failure(*args)
333
- result(Types::Result::Failure, *args)
334
- end
320
+ def failure(*args) = result(Types::Result::Failure, *args)
335
321
 
336
322
  # @param [Class] klass
337
323
  # @param [({Symbol => Object})] args
338
- def result(klass, *args)
339
- klass.new(*args)
340
- end
324
+ def result(klass, *args) = klass.new(*args)
341
325
 
342
326
  # @return [false]
343
- def default?
344
- false
345
- end
327
+ def default? = false
346
328
 
347
329
  # @param [Object, Dry::Struct] other
348
330
  # @return [Boolean]
349
- def ===(other)
350
- other.is_a?(self)
351
- end
331
+ def ===(other) = other.is_a?(self)
352
332
  alias_method :primitive?, :===
353
333
 
354
334
  # @return [true]
355
- def constrained?
356
- true
357
- end
335
+ def constrained? = true
358
336
 
359
337
  # @return [self]
360
- def primitive
361
- self
362
- end
338
+ def primitive = self
363
339
 
364
340
  # @return [false]
365
- def optional?
366
- false
367
- end
341
+ def optional? = false
368
342
 
369
343
  # @return [Proc]
370
344
  def to_proc
@@ -375,9 +349,7 @@ module Dry
375
349
  #
376
350
  # @param [Symbol] key Attribute name
377
351
  # @return [Boolean]
378
- def has_attribute?(key)
379
- schema.key?(key)
380
- end
352
+ def has_attribute?(key) = schema.key?(key)
381
353
 
382
354
  # Gets the list of attribute names
383
355
  #
@@ -455,11 +427,11 @@ module Dry
455
427
  # Constructs a type
456
428
  #
457
429
  # @return [Dry::Types::Type, Dry::Struct]
458
- def build_type(name, type = Undefined, &block)
430
+ def build_type(name, type = Undefined, &)
459
431
  type_object =
460
432
  if type.is_a?(::String)
461
433
  Types[type]
462
- elsif block.nil? && Undefined.equal?(type)
434
+ elsif !block_given? && Undefined.equal?(type)
463
435
  raise(
464
436
  ::ArgumentError,
465
437
  "you must supply a type or a block to `Dry::Struct.attribute`"
@@ -468,26 +440,32 @@ module Dry
468
440
  type
469
441
  end
470
442
 
471
- if block
472
- struct_builder.(name, type_object, &block)
443
+ if block_given?
444
+ struct_builder.(name, type_object, &)
473
445
  else
474
446
  type_object
475
447
  end
476
448
  end
477
449
  private :build_type
478
450
 
451
+ # @api private
479
452
  def define_accessors(keys)
480
- keys.each do |key|
481
- next if instance_methods.include?(key)
482
-
483
- class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
484
- def #{key} # def email
485
- @attributes[#{key.inspect}] # @attributes[:email]
486
- end # end
487
- RUBY
453
+ (keys - instance_methods).each do |key|
454
+ if valid_method_name?(key)
455
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
456
+ def #{key} # def email
457
+ @attributes[#{key.inspect}] # @attributes[:email]
458
+ end # end
459
+ RUBY
460
+ else
461
+ define_method(key) { @attributes[key] }
462
+ end
488
463
  end
489
464
  end
490
465
  private :define_accessors
466
+
467
+ # @api private
468
+ private def valid_method_name?(key) = key.to_s.match?(/\A[a-zA-Z_]\w*\z/)
491
469
  end
492
470
  end
493
471
  end
@@ -3,7 +3,7 @@
3
3
  module Dry
4
4
  class Struct
5
5
  # Raised when given input doesn't conform schema and constructor type
6
- Error = Class.new(TypeError)
6
+ Error = Class.new(::Dry::Types::CoercionError)
7
7
 
8
8
  # Raised when defining duplicate attributes
9
9
  class RepeatedAttributeError < ::ArgumentError
@@ -16,8 +16,8 @@ module Dry
16
16
 
17
17
  # Raised when a struct doesn't have an attribute
18
18
  class MissingAttributeError < ::KeyError
19
- def initialize(key)
20
- super("Missing attribute: #{key.inspect}")
19
+ def initialize(attribute:, klass:)
20
+ super("Missing attribute: #{attribute.inspect} on #{klass}")
21
21
  end
22
22
  end
23
23
 
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "super_diff"
4
+ require "super_diff/rspec"
5
+
6
+ module Dry
7
+ class Struct
8
+ def attributes_for_super_diff = attributes
9
+ end
10
+ end
@@ -3,3 +3,7 @@
3
3
  Dry::Struct.register_extension(:pretty_print) do
4
4
  require "dry/struct/extensions/pretty_print"
5
5
  end
6
+
7
+ Dry::Struct.register_extension(:super_diff) do
8
+ require "dry/struct/extensions/super_diff"
9
+ end
@@ -5,15 +5,15 @@ module Dry
5
5
  # Helper for {Struct#to_hash} implementation
6
6
  module Hashify
7
7
  # Converts value to hash recursively
8
- # @param [#to_hash, #map, Object] value
8
+ # @param [#to_hash, #to_ary, Object] value
9
9
  # @return [Hash, Array]
10
10
  def self.[](value)
11
- if value.is_a?(Struct)
12
- value.to_h.transform_values { |current| self[current] }
11
+ if value.is_a?(::Dry::Struct)
12
+ value.to_h
13
13
  elsif value.respond_to?(:to_hash)
14
- value.to_hash.transform_values { |current| self[current] }
14
+ value.to_hash.transform_values { self[_1] }
15
15
  elsif value.respond_to?(:to_ary)
16
- value.to_ary.map { |item| self[item] }
16
+ value.to_ary.map { self[_1] }
17
17
  else
18
18
  value
19
19
  end
@@ -43,17 +43,13 @@ module Dry
43
43
 
44
44
  private
45
45
 
46
- def type?(type)
47
- type.is_a?(Types::Type)
48
- end
46
+ def type?(type) = type.is_a?(Types::Type)
49
47
 
50
48
  def array?(type)
51
49
  type?(type) && !type.optional? && type.primitive.equal?(::Array)
52
50
  end
53
51
 
54
- def optional?(type)
55
- type?(type) && type.optional?
56
- end
52
+ def optional?(type) = type?(type) && type.optional?
57
53
 
58
54
  def parent(type)
59
55
  if array?(type)
@@ -95,9 +91,7 @@ module Dry
95
91
  visit(member)
96
92
  end
97
93
 
98
- def visit_nominal(*)
99
- Undefined
100
- end
94
+ def visit_nominal(*) = Undefined
101
95
 
102
96
  def visit_constructor(node)
103
97
  definition, * = node
@@ -18,7 +18,7 @@ module Dry
18
18
  # @return [Dry::Types::Result]
19
19
  def try(input)
20
20
  if input.is_a?(Struct)
21
- try_struct(input) { super }
21
+ ::Dry::Types::Result::Success.new(try_struct(input) { return super })
22
22
  else
23
23
  super
24
24
  end
@@ -28,7 +28,7 @@ module Dry
28
28
  # @param [Dry::Types::Type] type
29
29
  # @return [Dry::Types::Sum]
30
30
  def |(type)
31
- if type.is_a?(Class) && type <= Struct || type.is_a?(Sum)
31
+ if (type.is_a?(::Class) && type <= Struct) || type.is_a?(Sum)
32
32
  Sum.new(self, type)
33
33
  else
34
34
  super
@@ -36,9 +36,7 @@ module Dry
36
36
  end
37
37
 
38
38
  # @return [boolean]
39
- def ===(value)
40
- left === value || right === value
41
- end
39
+ def ===(value) = left === value || right === value
42
40
 
43
41
  protected
44
42
 
@@ -29,9 +29,7 @@ module Dry
29
29
  # @param (see ClassInterface#new)
30
30
  # @return [Value]
31
31
  # @see https://github.com/dkubb/ice_nine
32
- def self.new(*)
33
- ::IceNine.deep_freeze(super)
34
- end
32
+ def self.new(*) = ::IceNine.deep_freeze(super)
35
33
  end
36
34
 
37
35
  deprecate_constant :Value
@@ -3,6 +3,6 @@
3
3
  module Dry
4
4
  class Struct
5
5
  # @private
6
- VERSION = "1.6.0"
6
+ VERSION = "1.8.1"
7
7
  end
8
8
  end
data/lib/dry/struct.rb CHANGED
@@ -30,7 +30,7 @@ module Dry
30
30
  def self.Struct(attributes = Dry::Core::Constants::EMPTY_HASH, &block)
31
31
  Class.new(Dry::Struct) do
32
32
  attributes.each { |a, type| attribute a, type }
33
- module_eval(&block) if block
33
+ module_eval(&block) if block_given?
34
34
  end
35
35
  end
36
36
 
@@ -145,7 +145,13 @@ module Dry
145
145
  # rom_n_roda[:title] #=> 'Web Development with ROM and Roda'
146
146
  # rom_n_roda[:subtitle] #=> nil
147
147
  def [](name)
148
- @attributes.fetch(name) { raise MissingAttributeError, name }
148
+ @attributes.fetch(name) do
149
+ if self.class.attribute_names.include?(name)
150
+ nil
151
+ else
152
+ raise MissingAttributeError.new(attribute: name, klass: self.class)
153
+ end
154
+ end
149
155
  end
150
156
 
151
157
  # Converts the {Dry::Struct} to a hash with keys representing
@@ -200,8 +206,8 @@ module Dry
200
206
  resolve_defaults: false
201
207
  )
202
208
  self.class.load(__attributes__.merge(new_attributes))
203
- rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => e
204
- raise Error, "[#{self}.new] #{e}"
209
+ rescue Types::SchemaError, Types::MissingKeyError, Types::UnknownKeysError => exception
210
+ raise Error, "[#{self}.new] #{exception}"
205
211
  end
206
212
  alias_method :__new__, :new
207
213
 
@@ -215,9 +221,7 @@ module Dry
215
221
  # Pattern matching support
216
222
  #
217
223
  # @api private
218
- def deconstruct_keys(_keys)
219
- attributes
220
- end
224
+ def deconstruct_keys(_keys) = attributes
221
225
  end
222
226
  end
223
227
 
metadata CHANGED
@@ -1,83 +1,76 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
- - Piotr Solnica
8
- autorequire:
9
- bindir: bin
7
+ - Hanakai team
8
+ bindir: exe
10
9
  cert_chain: []
11
- date: 2022-11-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: dry-core
13
+ name: zeitwerk
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '1.0'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '2'
18
+ version: '2.6'
23
19
  type: :runtime
24
20
  prerelease: false
25
21
  version_requirements: !ruby/object:Gem::Requirement
26
22
  requirements:
27
23
  - - "~>"
28
24
  - !ruby/object:Gem::Version
29
- version: '1.0'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '2'
25
+ version: '2.6'
33
26
  - !ruby/object:Gem::Dependency
34
- name: dry-types
27
+ name: dry-core
35
28
  requirement: !ruby/object:Gem::Requirement
36
29
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '1.7'
40
- - - "<"
30
+ - - "~>"
41
31
  - !ruby/object:Gem::Version
42
- version: '2'
32
+ version: '1.1'
43
33
  type: :runtime
44
34
  prerelease: false
45
35
  version_requirements: !ruby/object:Gem::Requirement
46
36
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '1.7'
50
- - - "<"
37
+ - - "~>"
51
38
  - !ruby/object:Gem::Version
52
- version: '2'
39
+ version: '1.1'
53
40
  - !ruby/object:Gem::Dependency
54
- name: ice_nine
41
+ name: dry-types
55
42
  requirement: !ruby/object:Gem::Requirement
56
43
  requirements:
57
44
  - - "~>"
58
45
  - !ruby/object:Gem::Version
59
- version: '0.11'
46
+ version: '1.8'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 1.8.2
60
50
  type: :runtime
61
51
  prerelease: false
62
52
  version_requirements: !ruby/object:Gem::Requirement
63
53
  requirements:
64
54
  - - "~>"
65
55
  - !ruby/object:Gem::Version
66
- version: '0.11'
56
+ version: '1.8'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 1.8.2
67
60
  - !ruby/object:Gem::Dependency
68
- name: zeitwerk
61
+ name: ice_nine
69
62
  requirement: !ruby/object:Gem::Requirement
70
63
  requirements:
71
64
  - - "~>"
72
65
  - !ruby/object:Gem::Version
73
- version: '2.6'
66
+ version: '0.11'
74
67
  type: :runtime
75
68
  prerelease: false
76
69
  version_requirements: !ruby/object:Gem::Requirement
77
70
  requirements:
78
71
  - - "~>"
79
72
  - !ruby/object:Gem::Version
80
- version: '2.6'
73
+ version: '0.11'
81
74
  - !ruby/object:Gem::Dependency
82
75
  name: bundler
83
76
  requirement: !ruby/object:Gem::Requirement
@@ -136,10 +129,13 @@ dependencies:
136
129
  version: '0'
137
130
  description: Typed structs and value objects
138
131
  email:
139
- - piotr.solnica@gmail.com
132
+ - info@hanakai.org
140
133
  executables: []
141
134
  extensions: []
142
- extra_rdoc_files: []
135
+ extra_rdoc_files:
136
+ - CHANGELOG.md
137
+ - LICENSE
138
+ - README.md
143
139
  files:
144
140
  - CHANGELOG.md
145
141
  - LICENSE
@@ -153,6 +149,7 @@ files:
153
149
  - lib/dry/struct/errors.rb
154
150
  - lib/dry/struct/extensions.rb
155
151
  - lib/dry/struct/extensions/pretty_print.rb
152
+ - lib/dry/struct/extensions/super_diff.rb
156
153
  - lib/dry/struct/hashify.rb
157
154
  - lib/dry/struct/printer.rb
158
155
  - lib/dry/struct/struct_builder.rb
@@ -167,7 +164,7 @@ metadata:
167
164
  changelog_uri: https://github.com/dry-rb/dry-struct/blob/main/CHANGELOG.md
168
165
  source_code_uri: https://github.com/dry-rb/dry-struct
169
166
  bug_tracker_uri: https://github.com/dry-rb/dry-struct/issues
170
- post_install_message:
167
+ funding_uri: https://github.com/sponsors/hanami
171
168
  rdoc_options: []
172
169
  require_paths:
173
170
  - lib
@@ -175,15 +172,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
172
  requirements:
176
173
  - - ">="
177
174
  - !ruby/object:Gem::Version
178
- version: 2.7.0
175
+ version: 3.1.0
179
176
  required_rubygems_version: !ruby/object:Gem::Requirement
180
177
  requirements:
181
178
  - - ">="
182
179
  - !ruby/object:Gem::Version
183
180
  version: '0'
184
181
  requirements: []
185
- rubygems_version: 3.1.6
186
- signing_key:
182
+ rubygems_version: 3.6.9
187
183
  specification_version: 4
188
184
  summary: Typed structs and value objects
189
185
  test_files: []