u-struct 0.8.0 → 0.12.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 +4 -4
- data/.github/workflows/ci.yml +27 -0
- data/.gitignore +2 -0
- data/.vscode/settings.json +8 -0
- data/CHANGELOG.md +470 -11
- data/Gemfile +1 -1
- data/README.md +23 -4
- data/bin/prepare_coverage +27 -0
- data/bin/test +8 -0
- data/examples/person_1.rb +27 -0
- data/examples/person_2.rb +37 -0
- data/examples/rgb/color.rb +21 -0
- data/examples/rgb/number.rb +21 -0
- data/examples/rgb_1.rb +53 -0
- data/examples/rgb_2.rb +75 -0
- data/examples/rgb_3.rb +42 -0
- data/lib/micro/struct/factory/create_struct.rb +107 -0
- data/lib/micro/struct/factory/members.rb +37 -0
- data/lib/micro/struct/factory.rb +24 -0
- data/lib/micro/struct/features.rb +42 -19
- data/lib/micro/struct/version.rb +1 -1
- data/lib/micro/struct.rb +8 -3
- data/u-struct.gemspec +1 -1
- metadata +18 -8
- data/Gemfile.lock +0 -31
- data/lib/micro/struct/creator/create_module.rb +0 -65
- data/lib/micro/struct/creator/create_struct.rb +0 -43
- data/lib/micro/struct/creator.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7788d4a3412a447721c8d375a1844b9f000816ade2780925835e2a6ca222329c
|
4
|
+
data.tar.gz: 938d1c98f2f495aeca842a29a352e62a5f6565e96d7aed9ad01f27e8cadd08a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9c449b61842f114a0d90ce5b8c69d07c33599727cfb26e15a9d1455f79f7cd308d15b3d7d85f508a30c8b6717bf182b5a00dd960fb814d9cc648823fc882f01
|
7
|
+
data.tar.gz: b201b72d06fde813dfca89ff231a742c1d6fba92883133c4f12419e924830238c507d85f6d8e2e06c303033d3812df42e147acabe7742d5bfbc360163c739d34
|
@@ -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
data/CHANGELOG.md
CHANGED
@@ -1,37 +1,496 @@
|
|
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
|
+
[⬆️ Back to Top](#changelog-)
|
41
|
+
|
42
|
+
## [0.12.0] - 2021-12-22
|
43
|
+
|
44
|
+
### Added
|
45
|
+
|
46
|
+
- Add `Micro::Struct.instance` to create a struct instance from a given hash.
|
47
|
+
This could be useful to create constants or a singleton value.
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
person1 = Micro::Struct.instance(first_name: 'Rodrigo', last_name: 'Serradura')
|
51
|
+
# => #<struct first_name="Rodrigo", last_name="Serradura">
|
52
|
+
|
53
|
+
person1.first_name = 'John'
|
54
|
+
|
55
|
+
person1.first_name # => "John"
|
56
|
+
```
|
57
|
+
|
58
|
+
You can use the instance method after defining some struct feature.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
person2 = Micro::Struct.with(:readonly).instance(first_name: 'Rodrigo', last_name: 'Serradura')
|
62
|
+
# => #<struct first_name="Rodrigo", last_name="Serradura">
|
63
|
+
|
64
|
+
person2.first_name = 'John'
|
65
|
+
# NoMethodError (private method `first_name=' called for #<struct first_name="Rodrigo", last_name="Serradura">)
|
66
|
+
```
|
67
|
+
You can use pass a block to define some custom behavior to the struct instance.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
person3 = Micro::Struct.instance(first_name: 'Rodrigo', last_name: 'Serradura') do
|
71
|
+
def name
|
72
|
+
"#{first_name} #{last_name}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
person4 = Micro::Struct.with(:readonly).instance(first_name: 'Rodrigo', last_name: 'Serradura') do
|
77
|
+
def name
|
78
|
+
"#{first_name} #{last_name}"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
person3.name # => "Rodrigo Serradura"
|
83
|
+
person4.name # => "Rodrigo Serradura"
|
84
|
+
```
|
85
|
+
|
86
|
+
- Add `Micro::Struct.with(:exposed_features)` to expose the struct's configured features.
|
87
|
+
Via the methods: `.features` and `.__features__`.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
Person = Micro::Struct.with(:exposed_features, :readonly, :to_proc).new(:name)
|
91
|
+
|
92
|
+
Person.features
|
93
|
+
# => #<struct Micro::Struct::Features::Exposed
|
94
|
+
# names=[:readonly, :to_proc],
|
95
|
+
# options={:to_ary=>false, :to_hash=>false, :to_proc=>true, :readonly=>true, :instance_copy=>false}>
|
96
|
+
|
97
|
+
Person.__features__.equal?(Person.features) # `.__features__` is an alias of `.features` method
|
98
|
+
|
99
|
+
Person.features.names # => [:readonly, :to_proc]
|
100
|
+
Person.features.options # => {:to_ary=>false, :to_hash=>false, :to_proc=>true, :readonly=>true, :instance_copy=>false}
|
101
|
+
|
102
|
+
Person.features.option?(:to_proc) # => true
|
103
|
+
Person.features.option?(:readonly) # => true
|
104
|
+
|
105
|
+
Person.features.options?(:to_proc) # => true
|
106
|
+
Person.features.options?(:readonly) # => true
|
107
|
+
|
108
|
+
Person.features.options?(:to_proc, :readonly) # => true
|
109
|
+
Person.features.options?(:to_ary, :readonly) # => false
|
110
|
+
```
|
111
|
+
|
112
|
+
[⬆️ Back to Top](#changelog-)
|
113
|
+
|
114
|
+
## [0.11.0] - 2021-12-19
|
115
|
+
|
116
|
+
### Added
|
117
|
+
|
118
|
+
- Reduce the required Ruby version to `>= 2.2.0`.
|
119
|
+
- Set up a CI with Github actions.
|
120
|
+
- 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`.
|
121
|
+
|
122
|
+
[⬆️ Back to Top](#changelog-)
|
123
|
+
|
124
|
+
## [0.10.0] - 2021-12-15
|
125
|
+
|
126
|
+
### Changed
|
127
|
+
|
128
|
+
- Make `Micro::Struct.new` return a Ruby struct instead of a module.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
module RGB
|
132
|
+
Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
|
133
|
+
|
134
|
+
Color = Micro::Struct.new(:red, :green, :blue) do
|
135
|
+
def self.new(r, g, b)
|
136
|
+
__new__(
|
137
|
+
red: Number.new(r),
|
138
|
+
green: Number.new(g),
|
139
|
+
blue: Number.new(b),
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_hex
|
144
|
+
"##{red}#{green}#{blue}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
rgb_color = RGB::Color.new(1,5,255)
|
150
|
+
# => #<struct RGB::Color red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
|
151
|
+
|
152
|
+
rgb_color.to_hex
|
153
|
+
# => "#0105ff"
|
154
|
+
```
|
155
|
+
|
156
|
+
[⬆️ Back to Top](#changelog-)
|
157
|
+
|
158
|
+
## [0.9.0] - 2021-12-14
|
159
|
+
|
160
|
+
### Added
|
161
|
+
|
162
|
+
- Add `__new__` method and make `.new` its alias. You can use `__new__` when overwriting the module's `new`.
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
module RGB
|
166
|
+
Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
|
167
|
+
|
168
|
+
Color = Micro::Struct.new(:red, :green, :blue) do
|
169
|
+
def to_hex
|
170
|
+
"##{red}#{green}#{blue}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
module Color
|
175
|
+
def self.new(r, g, b)
|
176
|
+
__new__(
|
177
|
+
red: Number.new(r),
|
178
|
+
green: Number.new(g),
|
179
|
+
blue: Number.new(b),
|
180
|
+
)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
rgb_color = RGB::Color.new(1,5,255)
|
186
|
+
# => #<struct RGB::Color::Struct red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
|
187
|
+
|
188
|
+
rgb_color.to_hex
|
189
|
+
# => "#0105ff"
|
190
|
+
```
|
191
|
+
|
192
|
+
### Changed
|
193
|
+
|
194
|
+
- Change `:readonly` feature, now it doesn't require the `:instance_copy` by default.
|
195
|
+
So, If you want both features, you will need to declare them together.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
Person = Micro::Struct.with(:readonly).new(:name)
|
199
|
+
Persona = Micro::Struct.with(:readonly, :instance_copy).new(:name)
|
200
|
+
|
201
|
+
person = Person.new(name: 'Rodrigo')
|
202
|
+
persona = Persona.new(name: 'Serradura')
|
203
|
+
|
204
|
+
person.respond_to?(:name=) # false
|
205
|
+
persona.respond_to?(:name=) # false
|
206
|
+
|
207
|
+
person.respond_to?(:with) # false
|
208
|
+
persona.respond_to?(:with) # true
|
209
|
+
```
|
210
|
+
|
211
|
+
- Change `:to_ary` to invoke the `#to_a` method instead of defining it as an alias.
|
212
|
+
- Change `:to_hash` to invoke the `#to_h` method instead of defining it as an alias.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
module RGB
|
216
|
+
Number = ::Struct.new(:value) { def to_s; '%02x' % value; end }
|
217
|
+
|
218
|
+
Color = Micro::Struct.with(:readonly, :to_ary, :to_hash).new(:red, :green, :blue) do
|
219
|
+
def initialize(r, g, b)
|
220
|
+
super(Number.new(r), Number.new(g), Number.new(b))
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_hex
|
224
|
+
"##{red}#{green}#{blue}"
|
225
|
+
end
|
226
|
+
|
227
|
+
def to_a
|
228
|
+
[red, green, blue].map(&:value)
|
229
|
+
end
|
230
|
+
|
231
|
+
def to_h
|
232
|
+
{ r: red.value, g: green.value, b: blue.value }
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
rgb_color = RGB::Color.new(red: 1, green: 5, blue: 255)
|
238
|
+
# => #<struct RGB::Color::Struct red=#<struct RGB::Number value=1>, green=#<struct RGB::Number value=5>, blue=#<struct RGB::Number value=255>>
|
239
|
+
|
240
|
+
rgb_color.to_hex # => "#0105ff"
|
241
|
+
rgb_color.to_ary # => [1, 5, 255]
|
242
|
+
rgb_color.to_hash # => {:r=>1, :g=>5, :b=>255}
|
243
|
+
```
|
244
|
+
|
245
|
+
[⬆️ Back to Top](#changelog-)
|
246
|
+
|
3
247
|
## [0.8.0] - 2021-12-05
|
4
248
|
|
5
|
-
|
249
|
+
### Added
|
250
|
+
|
251
|
+
- Add `.===` to the module, it delegates the calling to its struct.
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
Person = Micro::Struct.new(:name)
|
255
|
+
|
256
|
+
person = Person.new(name: 'Rodrigo Serradura')
|
257
|
+
# => #<struct Person::Struct name="Rodrigo Serradura">
|
258
|
+
|
259
|
+
Person === person
|
260
|
+
# => true
|
261
|
+
```
|
262
|
+
|
263
|
+
[⬆️ Back to Top](#changelog-)
|
6
264
|
|
7
265
|
## [0.7.0] - 2021-12-04
|
8
266
|
|
9
|
-
|
267
|
+
### Added
|
268
|
+
|
269
|
+
- Add `required:` option to define required struct members.
|
270
|
+
|
271
|
+
```ruby
|
272
|
+
# All of the alternatives have the same equivalence.
|
273
|
+
|
274
|
+
Person = Micro::Struct.new(:first_name, :last_name)
|
275
|
+
|
276
|
+
Person = Micro::Struct.new(required: [:first_name, :last_name])
|
277
|
+
|
278
|
+
Person = Micro::Struct.new(:first_name, required: :last_name)
|
279
|
+
```
|
280
|
+
|
281
|
+
### Changed
|
282
|
+
|
283
|
+
- Remove the `_` from the `optional:` option.
|
284
|
+
|
285
|
+
```ruby
|
286
|
+
Person = Micro::Struct.new(
|
287
|
+
required: [:first_name, :last_name],
|
288
|
+
optional: :age
|
289
|
+
)
|
290
|
+
```
|
291
|
+
|
292
|
+
[⬆️ Back to Top](#changelog-)
|
10
293
|
|
11
294
|
## [0.6.0] - 2021-12-03
|
12
295
|
|
13
|
-
|
296
|
+
### Added
|
297
|
+
|
298
|
+
- Add the capability to create a struct with optional members.
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
Person = Micro::Struct.new(:first_name, _optional: :last_name)
|
302
|
+
|
303
|
+
Person.new
|
304
|
+
# ArgumentError (missing keyword: :first_name)
|
305
|
+
|
306
|
+
Person.new(first_name: 'Rodrigo')
|
307
|
+
# => #<struct Person::Struct first_name="Rodrigo", last_name=nil>
|
308
|
+
|
309
|
+
# --
|
310
|
+
|
311
|
+
Persona = Micro::Struct.new(_optional: [:first_name, :last_name])
|
312
|
+
|
313
|
+
Persona.new
|
314
|
+
# => #<struct Persona::Struct first_name=nil, last_name=nil>
|
315
|
+
```
|
316
|
+
|
317
|
+
[⬆️ Back to Top](#changelog-)
|
318
|
+
|
319
|
+
## [0.5.0] - 2021-12-02
|
320
|
+
|
321
|
+
### Added
|
322
|
+
|
323
|
+
- Add new feature `:instance_copy`. It instantiates a struct of the same kind from its current state.
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
Person = Micro::Struct.with(:instance_copy).new(:first_name, :last_name)
|
327
|
+
|
328
|
+
person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
|
329
|
+
# => #<struct Person::Struct first_name="Rodrigo", last_name="Serradura">
|
330
|
+
|
331
|
+
person.first_name = 'John'
|
332
|
+
# => "John"
|
333
|
+
|
334
|
+
person.inspect
|
335
|
+
# => #<struct Person::Struct first_name="John", last_name="Serradura">
|
336
|
+
|
337
|
+
new_person = person.with(last_name: 'Doe')
|
338
|
+
# => #<struct Person::Struct first_name="John", last_name="Doe">
|
339
|
+
|
340
|
+
person === new_person # => false
|
341
|
+
person.equal?(new_person) # => false
|
342
|
+
|
343
|
+
person.last_name # => "Serradura"
|
344
|
+
new_person.last_name # => "Doe"
|
345
|
+
```
|
346
|
+
|
347
|
+
- Add new feature `:readonly`. It sets members' writers private and requires the `:instance_copy` feature.
|
348
|
+
|
349
|
+
```ruby
|
350
|
+
Person = Micro::Struct.with(:readonly).new(:name)
|
351
|
+
|
352
|
+
person = Person.new(name: 'Rodrigo Serradura')
|
353
|
+
# => #<struct Person::Struct name="Rodrigo Serradura">
|
354
|
+
|
355
|
+
person.name = 'John Doe'
|
356
|
+
# NoMethodError (private method `name=' called for #<struct Person::Struct name="Rodrigo Serradura">)
|
357
|
+
|
358
|
+
new_person = person.with(name: 'John Doe')
|
359
|
+
# => #<struct Person::Struct name="John Doe">
|
360
|
+
|
361
|
+
person === new_person # => false
|
362
|
+
person.equal?(new_person) # => false
|
363
|
+
|
364
|
+
person.name # => "Rodrigo Serradura"
|
365
|
+
new_person.name # => "John Doe"
|
366
|
+
```
|
367
|
+
|
368
|
+
[⬆️ Back to Top](#changelog-)
|
369
|
+
|
370
|
+
## [0.4.0] - 2021-12-02
|
14
371
|
|
15
|
-
|
372
|
+
### Added
|
16
373
|
|
17
|
-
-
|
374
|
+
- Add `.members` to the module, it delegates the calling to its struct.
|
18
375
|
|
19
|
-
|
376
|
+
```ruby
|
377
|
+
Person = Micro::Struct.new(:first_name, :last_name)
|
20
378
|
|
21
|
-
|
379
|
+
Person.members # => [:first_name, :last_name]
|
380
|
+
```
|
381
|
+
|
382
|
+
- Add `Micro::Struct.with()` to enable or disable the creation of structs with custom features.
|
383
|
+
So now, you can create the structs with one, some, or all features. They are: `to_ary`, `to_hash`, `to_proc`.
|
384
|
+
|
385
|
+
```ruby
|
386
|
+
Person = Micro::Struct.with(:to_ary).new(:name)
|
387
|
+
|
388
|
+
person = Person.new(name: 'Rodrigo')
|
389
|
+
# => #<struct Person::Struct name="Rodrigo">
|
390
|
+
|
391
|
+
person.respond_to?(:to_ary) # => true
|
392
|
+
person.respond_to?(:to_hash) # => false
|
393
|
+
|
394
|
+
Person.respond_to?(:to_proc) # => false
|
395
|
+
```
|
396
|
+
|
397
|
+
[⬆️ Back to Top](#changelog-)
|
22
398
|
|
23
399
|
## [0.3.1] - 2021-12-02
|
24
400
|
|
25
|
-
|
401
|
+
### Fixed
|
402
|
+
|
403
|
+
- Fix the spec.files config of `u-struct.gemspec`.
|
404
|
+
|
405
|
+
[⬆️ Back to Top](#changelog-)
|
26
406
|
|
27
407
|
## [0.3.0] - 2021-12-02
|
28
408
|
|
29
|
-
|
409
|
+
### Added
|
410
|
+
|
411
|
+
- Add `lib/u-struct.rb` to allow the bundler to require the gem in an automatic way.
|
412
|
+
|
413
|
+
[⬆️ Back to Top](#changelog-)
|
30
414
|
|
31
415
|
## [0.2.0] - 2021-12-02
|
32
416
|
|
33
|
-
|
417
|
+
### Added
|
418
|
+
|
419
|
+
- Add `to_hash` as an alias of Struct's `to_h`.
|
420
|
+
|
421
|
+
```ruby
|
422
|
+
Person = Micro::Struct.new(:first_name, :last_name)
|
423
|
+
|
424
|
+
def print_first_and_last_name(first_name:, last_name:)
|
425
|
+
puts "#{first_name} #{last_name}"
|
426
|
+
end
|
427
|
+
|
428
|
+
person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
|
429
|
+
|
430
|
+
print_first_and_last_name(**person) # Rodrigo Serradura
|
431
|
+
```
|
432
|
+
|
433
|
+
[⬆️ Back to Top](#changelog-)
|
34
434
|
|
35
435
|
## [0.1.0] - 2021-12-02
|
36
436
|
|
37
|
-
|
437
|
+
### Added
|
438
|
+
|
439
|
+
- Create a module containing a Ruby struct with some custom features.
|
440
|
+
- The module's `.new` method receives the struct arguments as keyword arguments.
|
441
|
+
- The module's `.new` can receive a block as a regular `Struct` to add some custom behavior.
|
442
|
+
- The module's `to_proc` can instantiate the struct by receiving a hash.
|
443
|
+
- The module's struct has its initializer set up as private.
|
444
|
+
- Add `to_ary` as an alias of module's struct `to_a`.
|
445
|
+
|
446
|
+
```ruby
|
447
|
+
Person = Micro::Struct.new(:first_name, :last_name) do
|
448
|
+
def name
|
449
|
+
"#{first_name} #{last_name}"
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
# == Module's .new ==
|
454
|
+
|
455
|
+
Person.new
|
456
|
+
# ArgumentError (missing keywords: :first_name, :last_name)
|
457
|
+
|
458
|
+
Person.new(first_name: 'Rodrigo')
|
459
|
+
# ArgumentError (missing keyword: :last_name)
|
460
|
+
|
461
|
+
person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
|
462
|
+
# => #<struct Person::Struct first_name="Rodrigo", last_name="Serradura">
|
463
|
+
|
464
|
+
# == Struct's block - it sets up custom behavior ==
|
465
|
+
|
466
|
+
person.name # => "Rodrigo Serradura"
|
467
|
+
|
468
|
+
# == Struct's #to_ary ==
|
469
|
+
|
470
|
+
first_name, last_name = person
|
471
|
+
|
472
|
+
p first_name # => "Rodrigo"
|
473
|
+
p last_name # => "Serradura"
|
474
|
+
|
475
|
+
*first_and_last_name = person
|
476
|
+
|
477
|
+
p first_and_last_name # => ["Rodrigo", "Serradura"]
|
478
|
+
|
479
|
+
# == Module's .to_proc ==
|
480
|
+
|
481
|
+
[
|
482
|
+
{first_name: 'John', last_name: 'Doe'},
|
483
|
+
{first_name: 'Mary', last_name: 'Doe'}
|
484
|
+
].map(&Person)
|
485
|
+
# => [
|
486
|
+
# #<struct Person::Struct first_name="John", last_name="Doe">,
|
487
|
+
# #<struct Person::Struct first_name="Mary", last_name="Doe">
|
488
|
+
# ]
|
489
|
+
|
490
|
+
# == Struct's private initializer ==
|
491
|
+
|
492
|
+
Person::Struct.new
|
493
|
+
# => NoMethodError (private method `new' called for Person::Struct:Class)
|
494
|
+
```
|
495
|
+
|
496
|
+
[⬆️ Back to Top](#changelog-)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
Create powered Ruby structs
|
1
|
+
<p align="center">
|
2
|
+
<h1 align="center">🧱 μ-struct</h1>
|
3
|
+
<p align="center"><i>Create powered Ruby structs.</i></p>
|
4
|
+
<br>
|
5
|
+
</p>
|
6
|
+
|
7
|
+
<p align="center">
|
8
|
+
<img src="https://img.shields.io/badge/ruby%20%3E=%202.2,%20%3C%203.2-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
9
|
+
<a href="https://rubygems.org/gems/u-struct">
|
10
|
+
<img alt="Gem" src="https://img.shields.io/gem/v/u-struct.svg?style=flat-square">
|
11
|
+
</a>
|
12
|
+
<a href="https://github.com/serradura/u-struct/actions/workflows/ci.yml">
|
13
|
+
<img alt="Build Status" src="https://github.com/serradura/u-struct/actions/workflows/ci.yml/badge.svg">
|
14
|
+
</a>
|
15
|
+
<a href="https://codeclimate.com/github/serradura/u-struct/maintainability">
|
16
|
+
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/2cc0204411cc2b392b7a/maintainability">
|
17
|
+
</a>
|
18
|
+
<a href="https://codeclimate.com/github/serradura/u-struct/test_coverage">
|
19
|
+
<img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/2cc0204411cc2b392b7a/test_coverage">
|
20
|
+
</a>
|
21
|
+
</p>
|
4
22
|
|
5
23
|
## Installation
|
6
24
|
|
@@ -46,13 +64,14 @@ Micro::Struct.new(
|
|
46
64
|
Micro::Struct.new(:name) {}
|
47
65
|
|
48
66
|
# Available features (use one, many, or all) to create Structs with a special behavior:
|
49
|
-
# .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy)
|
67
|
+
# .with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features)
|
50
68
|
|
51
69
|
Micro::Struct.with(:to_ary).new(:name)
|
52
70
|
Micro::Struct.with(:to_ary, :to_hash).new(:name)
|
53
71
|
Micro::Struct.with(:to_ary, :to_hash, :to_proc).new(:name)
|
54
72
|
Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly).new(:name)
|
55
73
|
Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy).new(:name)
|
74
|
+
Micro::Struct.with(:to_ary, :to_hash, :to_proc, :readonly, :instance_copy, :exposed_features).new(:name)
|
56
75
|
|
57
76
|
# All of the possible combinations to create a Ruby Struct. ;)
|
58
77
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# Borrowed from https://gist.github.com/qortex/7e7c49f3731391a91ee898336183acef
|
4
|
+
|
5
|
+
# Temporary hack to get CodeClimate to work with SimpleCov 0.18 JSON format until issue is fixed
|
6
|
+
# upstream: https://github.com/codeclimate/test-reporter/issues/413
|
7
|
+
|
8
|
+
require "json"
|
9
|
+
|
10
|
+
filename = "coverage/.resultset.json"
|
11
|
+
contents = JSON.parse(File.read(filename))
|
12
|
+
|
13
|
+
def remove_lines_key(obj)
|
14
|
+
case obj
|
15
|
+
when Hash
|
16
|
+
obj.transform_values do |val|
|
17
|
+
val.is_a?(Hash) && val.key?("lines") ? val["lines"] : remove_lines_key(val)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
obj
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# overwrite
|
25
|
+
File.write(filename, JSON.generate(remove_lines_key(contents)))
|
26
|
+
|
27
|
+
puts Dir['coverage/.*.json']
|
data/bin/test
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/inline'
|
4
|
+
|
5
|
+
gemfile do
|
6
|
+
source 'https://rubygems.org'
|
7
|
+
|
8
|
+
gem 'u-struct', path: '..'
|
9
|
+
end
|
10
|
+
|
11
|
+
Person = Micro::Struct.new(:first_name, :last_name, optional: :age) do
|
12
|
+
def name
|
13
|
+
"#{first_name} #{last_name}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
person = Person.new(first_name: 'Rodrigo', last_name: 'Serradura')
|
18
|
+
|
19
|
+
puts format('first_name: %p', person.first_name)
|
20
|
+
puts format('last_name: %p', person.last_name)
|
21
|
+
puts format('name: %p', person.name)
|
22
|
+
puts format('age: %p', person.age)
|
23
|
+
puts
|
24
|
+
|
25
|
+
person.age = rand(18..100)
|
26
|
+
|
27
|
+
puts format('age: %p', person.age)
|