u-struct 0.9.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: '0765309623bfa9eb720102c66cd30f5ba785bdada60af711f19a03a51a7027bd'
4
- data.tar.gz: 216dd4920427d682c9e797e5ec0a8631486b5d8c0613391440bd0f94f2778824
3
+ metadata.gz: 3bae44de8a2fcfcebd5838c5aa282a16ca45e96f373cfb914f84849d1f05b46d
4
+ data.tar.gz: 7c4aa02beaaebf9a455d707d5e7cc654e7b3d3932b4555588aad0db3eff04806
5
5
  SHA512:
6
- metadata.gz: ed911103da03769ac8014a618d713b313e20a19a65074ac1a737f2d4cd1717dbdf521d0f7693665d840bdbff145e518afe3e7ef875b1eef55d2555e198bf8d62
7
- data.tar.gz: 683f94804b10f3ff03ed3f6ecbf4ff40c889dacf8dfd964496e8807974f96cbb611399fa21d95d73881a9c20d4dd0296975528cafc59dfbb20128471149c398a
6
+ metadata.gz: d08cb82f8392d7f960cb570ca2ddea82e931dd97c2ab9b6125a56aaca5a231d100d1e5f15bafa482214d0d63cd5c7d4f14d01bbbed3d5d07a2b60dc7f46024e9
7
+ data.tar.gz: 5bdc2d780807cbf09be36ed2d79453396a756642d3b088af74a79dc1d755328fa78786ed94167a1f7e8292b417614d17c606693f46ee4d8244c69ff7675d5900
@@ -0,0 +1,27 @@
1
+
2
+ name: build
3
+ on: [push]
4
+ jobs:
5
+ test:
6
+ runs-on: ubuntu-latest
7
+ strategy:
8
+ matrix:
9
+ ruby: [2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1.0-preview1]
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+ - uses: ruby/setup-ruby@v1
13
+ with:
14
+ ruby-version: ${{ matrix.ruby }}
15
+ bundler-cache: true
16
+ - name: Test and generate coverage
17
+ run: bin/test
18
+ - name: Format coverage
19
+ if: ${{ matrix.ruby >= 3 && matrix.ruby < 3.1 }}
20
+ run: bin/prepare_coverage
21
+ - uses: paambaati/codeclimate-action@v2.7.5
22
+ if: ${{ matrix.ruby >= 3 && matrix.ruby < 3.1 }}
23
+ env:
24
+ CC_TEST_REPORTER_ID: 8ce350edeb0772e94ffd678bbaca30d9c1293b9d9051a1689c79b91c21f5afd5
25
+ with:
26
+ debug: true
27
+ coverageLocations: coverage/.resultset.json:simplecov
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+
10
+ Gemfile.lock
@@ -0,0 +1,8 @@
1
+ {
2
+ "cSpell.enabled": true,
3
+ "cSpell.ignoreWords": [
4
+ "paambaati",
5
+ "resultset",
6
+ "simplecov"
7
+ ]
8
+ }
data/CHANGELOG.md CHANGED
@@ -1,41 +1,502 @@
1
+ # Changelog <!-- omit in toc -->
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ - [[Unreleased]](#unreleased)
9
+ - [[0.12.0] - 2021-12-22](#0120---2021-12-22)
10
+ - [Added](#added)
11
+ - [[0.11.0] - 2021-12-19](#0110---2021-12-19)
12
+ - [Added](#added-1)
13
+ - [[0.10.0] - 2021-12-15](#0100---2021-12-15)
14
+ - [Changed](#changed)
15
+ - [[0.9.0] - 2021-12-14](#090---2021-12-14)
16
+ - [Added](#added-2)
17
+ - [Changed](#changed-1)
18
+ - [[0.8.0] - 2021-12-05](#080---2021-12-05)
19
+ - [Added](#added-3)
20
+ - [[0.7.0] - 2021-12-04](#070---2021-12-04)
21
+ - [Added](#added-4)
22
+ - [Changed](#changed-2)
23
+ - [[0.6.0] - 2021-12-03](#060---2021-12-03)
24
+ - [Added](#added-5)
25
+ - [[0.5.0] - 2021-12-02](#050---2021-12-02)
26
+ - [Added](#added-6)
27
+ - [[0.4.0] - 2021-12-02](#040---2021-12-02)
28
+ - [Added](#added-7)
29
+ - [[0.3.1] - 2021-12-02](#031---2021-12-02)
30
+ - [Fixed](#fixed)
31
+ - [[0.3.0] - 2021-12-02](#030---2021-12-02)
32
+ - [Added](#added-8)
33
+ - [[0.2.0] - 2021-12-02](#020---2021-12-02)
34
+ - [Added](#added-9)
35
+ - [[0.1.0] - 2021-12-02](#010---2021-12-02)
36
+ - [Added](#added-10)
37
+
1
38
  ## [Unreleased]
2
39
 
40
+ [⬆️ &nbsp;Back to Top](#changelog-)
41
+
42
+ ## [1.0.0] - 2021-01-19
43
+
44
+ - Review and update docs and examples. ;)
45
+
46
+ [⬆️ &nbsp;Back to Top](#changelog-)
47
+
48
+ ## [0.12.0] - 2021-12-22
49
+
50
+ ### Added
51
+
52
+ - Add `Micro::Struct.instance` to create a struct instance from a given hash.
53
+ This could be useful to create constants or a singleton value.
54
+
55
+ ```ruby
56
+ person1 = Micro::Struct.instance(first_name: 'Rodrigo', last_name: 'Serradura')
57
+ # => #<struct first_name="Rodrigo", last_name="Serradura">
58
+
59
+ person1.first_name = 'John'
60
+
61
+ person1.first_name # => "John"
62
+ ```
63
+
64
+ You can use the instance method after defining some struct feature.
65
+
66
+ ```ruby
67
+ person2 = Micro::Struct.with(:readonly).instance(first_name: 'Rodrigo', last_name: 'Serradura')
68
+ # => #<struct first_name="Rodrigo", last_name="Serradura">
69
+
70
+ person2.first_name = 'John'
71
+ # NoMethodError (private method `first_name=' called for #<struct first_name="Rodrigo", last_name="Serradura">)
72
+ ```
73
+ You can use pass a block to define some custom behavior to the struct instance.
74
+
75
+ ```ruby
76
+ person3 = Micro::Struct.instance(first_name: 'Rodrigo', last_name: 'Serradura') do
77
+ def name
78
+ "#{first_name} #{last_name}"
79
+ end
80
+ end
81
+
82
+ person4 = Micro::Struct.with(:readonly).instance(first_name: 'Rodrigo', last_name: 'Serradura') do
83
+ def name
84
+ "#{first_name} #{last_name}"
85
+ end
86
+ end
87
+
88
+ person3.name # => "Rodrigo Serradura"
89
+ person4.name # => "Rodrigo Serradura"
90
+ ```
91
+
92
+ - Add `Micro::Struct.with(:exposed_features)` to expose the struct's configured features.
93
+ Via the methods: `.features` and `.__features__`.
94
+
95
+ ```ruby
96
+ Person = Micro::Struct.with(:exposed_features, :readonly, :to_proc).new(:name)
97
+
98
+ Person.features
99
+ # => #<struct Micro::Struct::Features::Exposed
100
+ # names=[:readonly, :to_proc],
101
+ # options={:to_ary=>false, :to_hash=>false, :to_proc=>true, :readonly=>true, :instance_copy=>false}>
102
+
103
+ Person.__features__.equal?(Person.features) # `.__features__` is an alias of `.features` method
104
+
105
+ Person.features.names # => [:readonly, :to_proc]
106
+ Person.features.options # => {:to_ary=>false, :to_hash=>false, :to_proc=>true, :readonly=>true, :instance_copy=>false}
107
+
108
+ Person.features.option?(:to_proc) # => true
109
+ Person.features.option?(:readonly) # => true
110
+
111
+ Person.features.options?(:to_proc) # => true
112
+ Person.features.options?(:readonly) # => true
113
+
114
+ Person.features.options?(:to_proc, :readonly) # => true
115
+ Person.features.options?(:to_ary, :readonly) # => false
116
+ ```
117
+
118
+ [⬆️ &nbsp;Back to Top](#changelog-)
119
+
120
+ ## [0.11.0] - 2021-12-19
121
+
122
+ ### Added
123
+
124
+ - Reduce the required Ruby version to `>= 2.2.0`.
125
+ - Set up a CI with Github actions.
126
+ - Test the codebase against the Ruby versions: `2.2`, `2.3`, `2.4`, `2.5`, `2.6`, `2.7`, `3.0` and `3.1.0-preview1`.
127
+
128
+ [⬆️ &nbsp;Back to Top](#changelog-)
129
+
130
+ ## [0.10.0] - 2021-12-15
131
+
132
+ ### Changed
133
+
134
+ - Make `Micro::Struct.new` return a Ruby struct instead of a module.
135
+
136
+ ```ruby
137
+ module RGB
138
+ Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
139
+
140
+ Color = Micro::Struct.new(:red, :green, :blue) do
141
+ def self.new(r, g, b)
142
+ __new__(
143
+ red: Number.new(r),
144
+ green: Number.new(g),
145
+ blue: Number.new(b),
146
+ )
147
+ end
148
+
149
+ def to_hex
150
+ "##{red}#{green}#{blue}"
151
+ end
152
+ end
153
+ end
154
+
155
+ rgb_color = RGB::Color.new(1,5,255)
156
+ # => #<struct RGB::Color red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
157
+
158
+ rgb_color.to_hex
159
+ # => "#0105ff"
160
+ ```
161
+
162
+ [⬆️ &nbsp;Back to Top](#changelog-)
163
+
3
164
  ## [0.9.0] - 2021-12-14
4
165
 
5
- - To-do
166
+ ### Added
167
+
168
+ - Add `__new__` method and make `.new` its alias. You can use `__new__` when overwriting the module's `new`.
169
+
170
+ ```ruby
171
+ module RGB
172
+ Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
173
+
174
+ Color = Micro::Struct.new(:red, :green, :blue) do
175
+ def to_hex
176
+ "##{red}#{green}#{blue}"
177
+ end
178
+ end
179
+
180
+ module Color
181
+ def self.new(r, g, b)
182
+ __new__(
183
+ red: Number.new(r),
184
+ green: Number.new(g),
185
+ blue: Number.new(b),
186
+ )
187
+ end
188
+ end
189
+ end
190
+
191
+ rgb_color = RGB::Color.new(1,5,255)
192
+ # => #<struct RGB::Color::Struct red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
193
+
194
+ rgb_color.to_hex
195
+ # => "#0105ff"
196
+ ```
197
+
198
+ ### Changed
199
+
200
+ - Change `:readonly` feature, now it doesn't require the `:instance_copy` by default.
201
+ So, If you want both features, you will need to declare them together.
202
+
203
+ ```ruby
204
+ Person = Micro::Struct.with(:readonly).new(:name)
205
+ Persona = Micro::Struct.with(:readonly, :instance_copy).new(:name)
206
+
207
+ person = Person.new(name: 'Rodrigo')
208
+ persona = Persona.new(name: 'Serradura')
209
+
210
+ person.respond_to?(:name=) # false
211
+ persona.respond_to?(:name=) # false
212
+
213
+ person.respond_to?(:with) # false
214
+ persona.respond_to?(:with) # true
215
+ ```
216
+
217
+ - Change `:to_ary` to invoke the `#to_a` method instead of defining it as an alias.
218
+ - Change `:to_hash` to invoke the `#to_h` method instead of defining it as an alias.
219
+
220
+ ```ruby
221
+ module RGB
222
+ Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
223
+
224
+ Color = Micro::Struct.with(:readonly, :to_ary, :to_hash).new(:red, :green, :blue) do
225
+ def initialize(r, g, b)
226
+ super(Number.new(r), Number.new(g), Number.new(b))
227
+ end
228
+
229
+ def to_hex
230
+ "##{red}#{green}#{blue}"
231
+ end
232
+
233
+ def to_a
234
+ [red, green, blue].map(&:value)
235
+ end
236
+
237
+ def to_h
238
+ { r: red.value, g: green.value, b: blue.value }
239
+ end
240
+ end
241
+ end
242
+
243
+ rgb_color = RGB::Color.new(red: 1, green: 5, blue: 255)
244
+ # => #<struct RGB::Color::Struct red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
245
+
246
+ rgb_color.to_hex # => "#0105ff"
247
+ rgb_color.to_ary # => [1, 5, 255]
248
+ rgb_color.to_hash # => {:r=>1, :g=>5, :b=>255}
249
+ ```
250
+
251
+ [⬆️ &nbsp;Back to Top](#changelog-)
6
252
 
7
253
  ## [0.8.0] - 2021-12-05
8
254
 
9
- - To-do
255
+ ### Added
256
+
257
+ - Add `.===` to the module, it delegates the calling to its struct.
258
+
259
+ ```ruby
260
+ Person = Micro::Struct.new(:name)
261
+
262
+ person = Person.new(name: 'Rodrigo Serradura')
263
+ # => #<struct Person::Struct name="Rodrigo Serradura">
264
+
265
+ Person === person
266
+ # => true
267
+ ```
268
+
269
+ [⬆️ &nbsp;Back to Top](#changelog-)
10
270
 
11
271
  ## [0.7.0] - 2021-12-04
12
272
 
13
- - To-do
273
+ ### Added
274
+
275
+ - Add `required:` option to define required struct members.
276
+
277
+ ```ruby
278
+ # All of the alternatives have the same equivalence.
279
+
280
+ Person = Micro::Struct.new(:first_name, :last_name)
281
+
282
+ Person = Micro::Struct.new(required: [:first_name, :last_name])
283
+
284
+ Person = Micro::Struct.new(:first_name, required: :last_name)
285
+ ```
286
+
287
+ ### Changed
288
+
289
+ - Remove the `_` from the `optional:` option.
290
+
291
+ ```ruby
292
+ Person = Micro::Struct.new(
293
+ required: [:first_name, :last_name],
294
+ optional: :age
295
+ )
296
+ ```
297
+
298
+ [⬆️ &nbsp;Back to Top](#changelog-)
14
299
 
15
300
  ## [0.6.0] - 2021-12-03
16
301
 
17
- - To-do
302
+ ### Added
303
+
304
+ - Add the capability to create a struct with optional members.
305
+
306
+ ```ruby
307
+ Person = Micro::Struct.new(:first_name, _optional: :last_name)
308
+
309
+ Person.new
310
+ # ArgumentError (missing keyword: :first_name)
311
+
312
+ Person.new(first_name: 'Rodrigo')
313
+ # => #<struct Person::Struct first_name="Rodrigo", last_name=nil>
314
+
315
+ # --
316
+
317
+ Persona = Micro::Struct.new(_optional: [:first_name, :last_name])
318
+
319
+ Persona.new
320
+ # => #<struct Persona::Struct first_name=nil, last_name=nil>
321
+ ```
322
+
323
+ [⬆️ &nbsp;Back to Top](#changelog-)
324
+
325
+ ## [0.5.0] - 2021-12-02
326
+
327
+ ### Added
328
+
329
+ - Add new feature `:instance_copy`. It instantiates a struct of the same kind from its current state.
330
+
331
+ ```ruby
332
+ Person = Micro::Struct.with(:instance_copy).new(:first_name, :last_name)
333
+
334
+ person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
335
+ # => #<struct Person::Struct first_name="Rodrigo", last_name="Serradura">
336
+
337
+ person.first_name = 'John'
338
+ # => "John"
339
+
340
+ person.inspect
341
+ # => #<struct Person::Struct first_name="John", last_name="Serradura">
342
+
343
+ new_person = person.with(last_name: 'Doe')
344
+ # => #<struct Person::Struct first_name="John", last_name="Doe">
345
+
346
+ person === new_person # => false
347
+ person.equal?(new_person) # => false
348
+
349
+ person.last_name # => "Serradura"
350
+ new_person.last_name # => "Doe"
351
+ ```
352
+
353
+ - Add new feature `:readonly`. It sets members' writers private and requires the `:instance_copy` feature.
354
+
355
+ ```ruby
356
+ Person = Micro::Struct.with(:readonly).new(:name)
357
+
358
+ person = Person.new(name: 'Rodrigo Serradura')
359
+ # => #<struct Person::Struct name="Rodrigo Serradura">
360
+
361
+ person.name = 'John Doe'
362
+ # NoMethodError (private method `name=' called for #<struct Person::Struct name="Rodrigo Serradura">)
363
+
364
+ new_person = person.with(name: 'John Doe')
365
+ # => #<struct Person::Struct name="John Doe">
366
+
367
+ person === new_person # => false
368
+ person.equal?(new_person) # => false
369
+
370
+ person.name # => "Rodrigo Serradura"
371
+ new_person.name # => "John Doe"
372
+ ```
373
+
374
+ [⬆️ &nbsp;Back to Top](#changelog-)
375
+
376
+ ## [0.4.0] - 2021-12-02
18
377
 
19
- ## [0.5.0] - 2021-12-03
378
+ ### Added
20
379
 
21
- - To-do
380
+ - Add `.members` to the module, it delegates the calling to its struct.
22
381
 
23
- ## [0.4.0] - 2021-12-03
382
+ ```ruby
383
+ Person = Micro::Struct.new(:first_name, :last_name)
24
384
 
25
- - To-do
385
+ Person.members # => [:first_name, :last_name]
386
+ ```
387
+
388
+ - Add `Micro::Struct.with()` to enable or disable the creation of structs with custom features.
389
+ So now, you can create the structs with one, some, or all features. They are: `to_ary`, `to_hash`, `to_proc`.
390
+
391
+ ```ruby
392
+ Person = Micro::Struct.with(:to_ary).new(:name)
393
+
394
+ person = Person.new(name: 'Rodrigo')
395
+ # => #<struct Person::Struct name="Rodrigo">
396
+
397
+ person.respond_to?(:to_ary) # => true
398
+ person.respond_to?(:to_hash) # => false
399
+
400
+ Person.respond_to?(:to_proc) # => false
401
+ ```
402
+
403
+ [⬆️ &nbsp;Back to Top](#changelog-)
26
404
 
27
405
  ## [0.3.1] - 2021-12-02
28
406
 
29
- - To-do
407
+ ### Fixed
408
+
409
+ - Fix the spec.files config of `u-struct.gemspec`.
410
+
411
+ [⬆️ &nbsp;Back to Top](#changelog-)
30
412
 
31
413
  ## [0.3.0] - 2021-12-02
32
414
 
33
- - To-do
415
+ ### Added
416
+
417
+ - Add `lib/u-struct.rb` to allow the bundler to require the gem in an automatic way.
418
+
419
+ [⬆️ &nbsp;Back to Top](#changelog-)
34
420
 
35
421
  ## [0.2.0] - 2021-12-02
36
422
 
37
- - To-do
423
+ ### Added
424
+
425
+ - Add `to_hash` as an alias of Struct's `to_h`.
426
+
427
+ ```ruby
428
+ Person = Micro::Struct.new(:first_name, :last_name)
429
+
430
+ def print_first_and_last_name(first_name:, last_name:)
431
+ puts "#{first_name} #{last_name}"
432
+ end
433
+
434
+ person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
435
+
436
+ print_first_and_last_name(**person) # Rodrigo Serradura
437
+ ```
438
+
439
+ [⬆️ &nbsp;Back to Top](#changelog-)
38
440
 
39
441
  ## [0.1.0] - 2021-12-02
40
442
 
41
- - Initial release
443
+ ### Added
444
+
445
+ - Create a module containing a Ruby struct with some custom features.
446
+ - The module's `.new` method receives the struct arguments as keyword arguments.
447
+ - The module's `.new` can receive a block as a regular `Struct` to add some custom behavior.
448
+ - The module's `to_proc` can instantiate the struct by receiving a hash.
449
+ - The module's struct has its initializer set up as private.
450
+ - Add `to_ary` as an alias of module's struct `to_a`.
451
+
452
+ ```ruby
453
+ Person = Micro::Struct.new(:first_name, :last_name) do
454
+ def name
455
+ "#{first_name} #{last_name}"
456
+ end
457
+ end
458
+
459
+ # == Module's .new ==
460
+
461
+ Person.new
462
+ # ArgumentError (missing keywords: :first_name, :last_name)
463
+
464
+ Person.new(first_name: 'Rodrigo')
465
+ # ArgumentError (missing keyword: :last_name)
466
+
467
+ person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
468
+ # => #<struct Person::Struct first_name="Rodrigo", last_name="Serradura">
469
+
470
+ # == Struct's block - it sets up custom behavior ==
471
+
472
+ person.name # => "Rodrigo Serradura"
473
+
474
+ # == Struct's #to_ary ==
475
+
476
+ first_name, last_name = person
477
+
478
+ p first_name # => "Rodrigo"
479
+ p last_name # => "Serradura"
480
+
481
+ *first_and_last_name = person
482
+
483
+ p first_and_last_name # => ["Rodrigo", "Serradura"]
484
+
485
+ # == Module's .to_proc ==
486
+
487
+ [
488
+ {first_name: 'John', last_name: 'Doe'},
489
+ {first_name: 'Mary', last_name: 'Doe'}
490
+ ].map(&Person)
491
+ # => [
492
+ # #<struct Person::Struct first_name="John", last_name="Doe">,
493
+ # #<struct Person::Struct first_name="Mary", last_name="Doe">
494
+ # ]
495
+
496
+ # == Struct's private initializer ==
497
+
498
+ Person::Struct.new
499
+ # => NoMethodError (private method `new' called for Person::Struct:Class)
500
+ ```
501
+
502
+ [⬆️ &nbsp;Back to Top](#changelog-)
data/Gemfile CHANGED
@@ -8,4 +8,4 @@ gemspec
8
8
  gem 'rake', '~> 13.0'
9
9
 
10
10
  gem 'minitest', '~> 5.0'
11
- gem 'simplecov', '~> 0.21.2'
11
+ gem 'simplecov', '~> 0.21.2' if RUBY_VERSION >= '2.5.0'