u-struct 0.9.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: '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'