u-attributes 2.0.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Gemfile +10 -1
- data/README.md +274 -47
- data/lib/micro/attributes.rb +69 -20
- data/lib/micro/attributes/diff.rb +26 -14
- data/lib/micro/attributes/features.rb +72 -77
- data/lib/micro/attributes/features/activemodel_validations.rb +2 -2
- data/lib/micro/attributes/features/initialize/strict.rb +6 -26
- data/lib/micro/attributes/features/keys_as_symbol.rb +31 -0
- data/lib/micro/attributes/macros.rb +58 -10
- data/lib/micro/attributes/utils.rb +48 -9
- data/lib/micro/attributes/version.rb +1 -1
- data/lib/micro/attributes/with.rb +107 -25
- data/u-attributes.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62c6ad9683f0824be6a32648028f25a97ba88a10c7fbdd0b9a2ccfbfe275961b
|
4
|
+
data.tar.gz: d110a1b4220af76a7f14753cb1ca5067428f06db026466e095d54a22ee46f86f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24703dcd81aa785fe00b77a741434ad84600243f4bb132d2bbbce2b5a310d4f2b931c2b6ea41e311a2bcf07876296bd03d8e6c39a92905bc9a4f745fdb30a094
|
7
|
+
data.tar.gz: 8172811ddaf44a3099e66f63cea5aed99d5c1a63a77944dc1e98c16fa0378603498fbdfe0c77f7220244c8d7b977801a75bd01facc875fb05f0bd1aed0171cc5
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
gem 'u-case', '~> 4.0'
|
4
|
+
|
3
5
|
activemodel_version = ENV.fetch('ACTIVEMODEL_VERSION', '6.1')
|
4
6
|
|
5
7
|
activemodel = case activemodel_version
|
@@ -18,9 +20,16 @@ if activemodel_version < '6.1'
|
|
18
20
|
gem 'activesupport', activemodel, require: false
|
19
21
|
end
|
20
22
|
|
23
|
+
simplecov_version =
|
24
|
+
case RUBY_VERSION
|
25
|
+
when /\A2.[23]/ then '~> 0.17.1'
|
26
|
+
when /\A2.4/ then '~> 0.18.5'
|
27
|
+
else '~> 0.19'
|
28
|
+
end
|
29
|
+
|
21
30
|
group :test do
|
22
31
|
gem 'minitest', activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
|
23
|
-
gem 'simplecov', require: false
|
32
|
+
gem 'simplecov', simplecov_version, require: false
|
24
33
|
end
|
25
34
|
|
26
35
|
# Specify your gem's dependencies in u-attributes.gemspec
|
data/README.md
CHANGED
@@ -1,21 +1,41 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=main)](https://travis-ci.com/serradura/u-attributes)
|
4
|
-
[![Maintainability](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability)](https://codeclimate.com/github/serradura/u-attributes/maintainability)
|
5
|
-
[![Test Coverage](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage)](https://codeclimate.com/github/serradura/u-attributes/test_coverage)
|
1
|
+
<p align="center">
|
2
|
+
<img src="./assets/u-attributes_logo_v1.png" alt='Create "immutable" objects. No setters, just getters!'>
|
6
3
|
|
7
|
-
|
8
|
-
|
4
|
+
<p align="center"><i>Create "immutable" objects. No setters, just getters!</i></p>
|
5
|
+
<br>
|
6
|
+
</p>
|
7
|
+
|
8
|
+
<p align="center">
|
9
|
+
<img src="https://img.shields.io/badge/ruby-2.2+-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
10
|
+
|
11
|
+
<a href="https://rubygems.org/gems/u-attributes">
|
12
|
+
<img alt="Gem" src="https://img.shields.io/gem/v/u-attributes.svg?style=flat-square">
|
13
|
+
</a>
|
14
|
+
|
15
|
+
<a href="https://travis-ci.com/serradura/u-attributes">
|
16
|
+
<img alt="Build Status" src="https://travis-ci.com/serradura/u-attributes.svg?branch=main">
|
17
|
+
</a>
|
18
|
+
|
19
|
+
<a href="https://codeclimate.com/github/serradura/u-attributes/maintainability">
|
20
|
+
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability">
|
21
|
+
</a>
|
22
|
+
|
23
|
+
<a href="https://codeclimate.com/github/serradura/u-attributes/test_coverage">
|
24
|
+
<img alt="Test Coverage" src="https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage">
|
25
|
+
</a>
|
26
|
+
</p>
|
9
27
|
|
10
28
|
This gem allows you to define "immutable" objects, and your objects will have only getters and no setters.
|
11
29
|
So, if you change [[1](#with_attribute)] [[2](#with_attributes)] some object attribute, you will have a new object instance. That is, you transform the object instead of modifying it.
|
12
30
|
|
13
|
-
|
31
|
+
# Table of contents <!-- omit in toc -->
|
14
32
|
- [Installation](#installation)
|
15
33
|
- [Compatibility](#compatibility)
|
16
34
|
- [Usage](#usage)
|
17
35
|
- [How to define attributes?](#how-to-define-attributes)
|
18
36
|
- [`Micro::Attributes#attributes=`](#microattributesattributes)
|
37
|
+
- [How to extract attributes from an object or hash?](#how-to-extract-attributes-from-an-object-or-hash)
|
38
|
+
- [Is it possible to define an attribute as required?](#is-it-possible-to-define-an-attribute-as-required)
|
19
39
|
- [`Micro::Attributes#attribute`](#microattributesattribute)
|
20
40
|
- [`Micro::Attributes#attribute!`](#microattributesattribute-1)
|
21
41
|
- [How to define multiple attributes?](#how-to-define-multiple-attributes)
|
@@ -27,6 +47,15 @@ So, if you change [[1](#with_attribute)] [[2](#with_attributes)] some object att
|
|
27
47
|
- [Is it possible to inherit the attributes?](#is-it-possible-to-inherit-the-attributes)
|
28
48
|
- [`.attribute!()`](#attribute)
|
29
49
|
- [How to query the attributes?](#how-to-query-the-attributes)
|
50
|
+
- [`.attributes`](#attributes)
|
51
|
+
- [`.attribute?()`](#attribute-1)
|
52
|
+
- [`#attribute?()`](#attribute-2)
|
53
|
+
- [`#attributes()`](#attributes-1)
|
54
|
+
- [`#attributes(keys_as:)`](#attributeskeys_as)
|
55
|
+
- [`#attributes(*names)`](#attributesnames)
|
56
|
+
- [`#attributes([names])`](#attributesnames-1)
|
57
|
+
- [`#attributes(with:, without:)`](#attributeswith-without)
|
58
|
+
- [`#defined_attributes`](#defined_attributes)
|
30
59
|
- [Built-in extensions](#built-in-extensions)
|
31
60
|
- [Picking specific features](#picking-specific-features)
|
32
61
|
- [`Micro::Attributes.with`](#microattributeswith)
|
@@ -38,6 +67,7 @@ So, if you change [[1](#with_attribute)] [[2](#with_attributes)] some object att
|
|
38
67
|
- [Diff extension](#diff-extension)
|
39
68
|
- [Initialize extension](#initialize-extension)
|
40
69
|
- [Strict mode](#strict-mode)
|
70
|
+
- [Keys as symbol extension](#keys-as-symbol-extension)
|
41
71
|
- [Development](#development)
|
42
72
|
- [Contributing](#contributing)
|
43
73
|
- [License](#license)
|
@@ -55,7 +85,7 @@ gem 'u-attributes'
|
|
55
85
|
|
56
86
|
| u-attributes | branch | ruby | activemodel |
|
57
87
|
| -------------- | ------- | -------- | ------------- |
|
58
|
-
| 2.
|
88
|
+
| 2.4.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
|
59
89
|
| 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
|
60
90
|
|
61
91
|
> **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes.
|
@@ -66,9 +96,9 @@ gem 'u-attributes'
|
|
66
96
|
|
67
97
|
## How to define attributes?
|
68
98
|
|
69
|
-
|
70
|
-
# By default you must to define the class constructor.
|
99
|
+
By default, you must define the class constructor.
|
71
100
|
|
101
|
+
```ruby
|
72
102
|
class Person
|
73
103
|
include Micro::Attributes
|
74
104
|
|
@@ -116,6 +146,66 @@ person.age # 20
|
|
116
146
|
person.name # John Doe
|
117
147
|
```
|
118
148
|
|
149
|
+
#### How to extract attributes from an object or hash?
|
150
|
+
|
151
|
+
You can extract attributes using the `extract_attributes_from` method, it will try to fetch attributes from the
|
152
|
+
object using either the `object[attribute_key]` accessor or the reader method `object.attribute_key`.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class Person
|
156
|
+
include Micro::Attributes
|
157
|
+
|
158
|
+
attribute :age
|
159
|
+
attribute :name, default: 'John Doe'
|
160
|
+
|
161
|
+
def initialize(user:)
|
162
|
+
self.attributes = extract_attributes_from(user)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# extracting from an object
|
167
|
+
|
168
|
+
class User
|
169
|
+
attr_accessor :age, :name
|
170
|
+
end
|
171
|
+
|
172
|
+
user = User.new
|
173
|
+
user.age = 20
|
174
|
+
|
175
|
+
person = Person.new(user: user)
|
176
|
+
|
177
|
+
person.age # 20
|
178
|
+
person.name # John Doe
|
179
|
+
|
180
|
+
# extracting from a hash
|
181
|
+
|
182
|
+
another_person = Person.new(user: { age: 55, name: 'Julia Not Roberts' })
|
183
|
+
|
184
|
+
another_person.age # 55
|
185
|
+
another_person.name # Julia Not Roberts
|
186
|
+
```
|
187
|
+
|
188
|
+
#### Is it possible to define an attribute as required?
|
189
|
+
|
190
|
+
You only need to use the `required: true` option.
|
191
|
+
|
192
|
+
But to this work, you need to assign the attributes using the [`#attributes=`](#microattributesattributes) method or the extensions: [initialize](#initialize-extension), [activemodel_validations](#activemodelvalidation-extension).
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
class Person
|
196
|
+
include Micro::Attributes
|
197
|
+
|
198
|
+
attribute :age
|
199
|
+
attribute :name, required: true
|
200
|
+
|
201
|
+
def initialize(attributes)
|
202
|
+
self.attributes = attributes
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
Person.new(age: 32) # ArgumentError (missing keyword: :name)
|
207
|
+
```
|
208
|
+
|
119
209
|
[⬆️ Back to Top](#table-of-contents-)
|
120
210
|
|
121
211
|
### `Micro::Attributes#attribute`
|
@@ -185,7 +275,7 @@ Use `Micro::Attributes.with(:initialize)` to define a constructor to assign the
|
|
185
275
|
class Person
|
186
276
|
include Micro::Attributes.with(:initialize)
|
187
277
|
|
188
|
-
attribute :age
|
278
|
+
attribute :age, required: true
|
189
279
|
attribute :name, default: 'John Doe'
|
190
280
|
end
|
191
281
|
|
@@ -240,10 +330,9 @@ class Person
|
|
240
330
|
end
|
241
331
|
```
|
242
332
|
|
243
|
-
There are
|
333
|
+
There are two different strategies to define default values.
|
244
334
|
1. Pass a regular object, like in the previous example.
|
245
335
|
2. Pass a `proc`/`lambda`, and if it has an argument you will receive the attribute value to do something before assign it.
|
246
|
-
3. Pass a **callable**, that is, a `class`, `module` or `instance` which responds to the `call` method. The behavior will be like the previous item (`proc`/`lambda`).
|
247
336
|
|
248
337
|
```ruby
|
249
338
|
class Person
|
@@ -258,7 +347,9 @@ end
|
|
258
347
|
|
259
348
|
## The strict initializer
|
260
349
|
|
261
|
-
Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords.
|
350
|
+
Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords.
|
351
|
+
|
352
|
+
In other words, it is equivalent to you define all the attributes using the [`required: true` option](#is-it-possible-to-define-an-attribute-as-required).
|
262
353
|
|
263
354
|
```ruby
|
264
355
|
class StrictPerson
|
@@ -338,63 +429,155 @@ beta_person.age # 0
|
|
338
429
|
|
339
430
|
## How to query the attributes?
|
340
431
|
|
432
|
+
All of the methods that will be explained can be used with any of the built-in extensions.
|
433
|
+
|
434
|
+
**PS:** We will use the class below for all of the next examples.
|
435
|
+
|
341
436
|
```ruby
|
342
437
|
class Person
|
343
438
|
include Micro::Attributes
|
344
439
|
|
345
440
|
attribute :age
|
346
|
-
attribute :
|
441
|
+
attribute :first_name, default: 'John'
|
442
|
+
attribute :last_name, default: 'Doe'
|
347
443
|
|
348
444
|
def initialize(options)
|
349
445
|
self.attributes = options
|
350
446
|
end
|
447
|
+
|
448
|
+
def name
|
449
|
+
"#{first_name} #{last_name}"
|
450
|
+
end
|
351
451
|
end
|
452
|
+
```
|
453
|
+
|
454
|
+
### `.attributes`
|
455
|
+
|
456
|
+
Listing all the class attributes.
|
352
457
|
|
353
|
-
|
354
|
-
|
355
|
-
|
458
|
+
```ruby
|
459
|
+
Person.attributes # ["age", "first_name", "last_name"]
|
460
|
+
```
|
356
461
|
|
357
|
-
|
462
|
+
### `.attribute?()`
|
358
463
|
|
359
|
-
|
360
|
-
|
361
|
-
|
464
|
+
Checking the existence of some attribute.
|
465
|
+
|
466
|
+
```ruby
|
467
|
+
Person.attribute?(:first_name) # true
|
468
|
+
Person.attribute?('first_name') # true
|
362
469
|
|
363
|
-
Person.attribute?(:name) # true
|
364
|
-
Person.attribute?('name') # true
|
365
470
|
Person.attribute?('foo') # false
|
366
471
|
Person.attribute?(:foo) # false
|
472
|
+
```
|
367
473
|
|
368
|
-
|
474
|
+
### `#attribute?()`
|
369
475
|
|
370
|
-
|
476
|
+
Checking the existence of some attribute in an instance.
|
371
477
|
|
372
|
-
|
373
|
-
|
374
|
-
#---------------#
|
478
|
+
```ruby
|
479
|
+
person = Person.new(age: 20)
|
375
480
|
|
376
481
|
person.attribute?(:name) # true
|
377
482
|
person.attribute?('name') # true
|
483
|
+
|
378
484
|
person.attribute?('foo') # false
|
379
485
|
person.attribute?(:foo) # false
|
486
|
+
```
|
380
487
|
|
381
|
-
|
382
|
-
# #attributes() #
|
383
|
-
#---------------#
|
488
|
+
### `#attributes()`
|
384
489
|
|
385
|
-
|
386
|
-
|
490
|
+
Fetching all the attributes with their values.
|
491
|
+
|
492
|
+
```ruby
|
493
|
+
person1 = Person.new(age: 20)
|
494
|
+
person1.attributes # {"age"=>20, "first_name"=>"John", "last_name"=>"Doe"}
|
495
|
+
|
496
|
+
person2 = Person.new(first_name: 'Rodrigo', last_name: 'Rodrigues')
|
497
|
+
person2.attributes # {"age"=>nil, "first_name"=>"Rodrigo", "last_name"=>"Rodrigues"}
|
498
|
+
```
|
387
499
|
|
388
|
-
|
389
|
-
# #attributes(*names) #
|
390
|
-
#---------------------#
|
500
|
+
#### `#attributes(keys_as:)`
|
391
501
|
|
392
|
-
|
393
|
-
# Returns a hash containing the given keys (in their types).
|
502
|
+
Use the `keys_as:` option with `Symbol`/`:symbol` or `String`/`:string` to transform the attributes hash keys.
|
394
503
|
|
395
|
-
|
396
|
-
|
397
|
-
|
504
|
+
```ruby
|
505
|
+
person1 = Person.new(age: 20)
|
506
|
+
person2 = Person.new(first_name: 'Rodrigo', last_name: 'Rodrigues')
|
507
|
+
|
508
|
+
person1.attributes(keys_as: Symbol) # {:age=>20, :first_name=>"John", :last_name=>"Doe"}
|
509
|
+
person2.attributes(keys_as: String) # {"age"=>nil, "first_name"=>"Rodrigo", "last_name"=>"Rodrigues"}
|
510
|
+
|
511
|
+
person1.attributes(keys_as: :symbol) # {:age=>20, :first_name=>"John", :last_name=>"Doe"}
|
512
|
+
person2.attributes(keys_as: :string) # {"age"=>nil, "first_name"=>"Rodrigo", "last_name"=>"Rodrigues"}
|
513
|
+
```
|
514
|
+
|
515
|
+
#### `#attributes(*names)`
|
516
|
+
|
517
|
+
Slices the attributes to include only the given keys (in their types).
|
518
|
+
|
519
|
+
```ruby
|
520
|
+
person = Person.new(age: 20)
|
521
|
+
|
522
|
+
person.attributes(:age) # {:age => 20}
|
523
|
+
person.attributes(:age, :first_name) # {:age => 20, :first_name => "John"}
|
524
|
+
person.attributes('age', 'last_name') # {"age" => 20, "last_name" => "Doe"}
|
525
|
+
|
526
|
+
person.attributes(:age, 'last_name') # {:age => 20, "last_name" => "Doe"}
|
527
|
+
|
528
|
+
# You could also use the keys_as: option to ensure the same type for all of the hash keys.
|
529
|
+
|
530
|
+
person.attributes(:age, 'last_name', keys_as: Symbol) # {:age=>20, :last_name=>"Doe"}
|
531
|
+
```
|
532
|
+
|
533
|
+
#### `#attributes([names])`
|
534
|
+
|
535
|
+
As the previous example, this methods accepts a list of keys to slice the attributes.
|
536
|
+
|
537
|
+
```ruby
|
538
|
+
person = Person.new(age: 20)
|
539
|
+
|
540
|
+
person.attributes([:age]) # {:age => 20}
|
541
|
+
person.attributes([:age, :first_name]) # {:age => 20, :first_name => "John"}
|
542
|
+
person.attributes(['age', 'last_name']) # {"age" => 20, "last_name" => "Doe"}
|
543
|
+
|
544
|
+
person.attributes([:age, 'last_name']) # {:age => 20, "last_name" => "Doe"}
|
545
|
+
|
546
|
+
# You could also use the keys_as: option to ensure the same type for all of the hash keys.
|
547
|
+
|
548
|
+
person.attributes([:age, 'last_name'], keys_as: Symbol) # {:age=>20, :last_name=>"Doe"}
|
549
|
+
```
|
550
|
+
|
551
|
+
#### `#attributes(with:, without:)`
|
552
|
+
|
553
|
+
Use the `with:` option to include any method value of the instance inside of the hash, and,
|
554
|
+
you can use the `without:` option to exclude one or more attribute keys from the final hash.
|
555
|
+
|
556
|
+
```ruby
|
557
|
+
person = Person.new(age: 20)
|
558
|
+
|
559
|
+
person.attributes(without: :age) # {"first_name"=>"John", "last_name"=>"Doe"}
|
560
|
+
person.attributes(without: [:age, :last_name]) # {"first_name"=>"John"}
|
561
|
+
|
562
|
+
person.attributes(with: [:name], without: [:first_name, :last_name]) # {"age"=>20, "name"=>"John Doe"}
|
563
|
+
|
564
|
+
# To achieves the same output of the previous example, use the attribute names to slice only them.
|
565
|
+
|
566
|
+
person.attributes(:age, with: [:name]) # {:age=>20, "name"=>"John Doe"}
|
567
|
+
|
568
|
+
# You could also use the keys_as: option to ensure the same type for all of the hash keys.
|
569
|
+
|
570
|
+
person.attributes(:age, with: [:name], keys_as: Symbol) # {:age=>20, :name=>"John Doe"}
|
571
|
+
```
|
572
|
+
|
573
|
+
### `#defined_attributes`
|
574
|
+
|
575
|
+
Listing all the available attributes.
|
576
|
+
|
577
|
+
```ruby
|
578
|
+
person = Person.new(age: 20)
|
579
|
+
|
580
|
+
person.defined_attributes # ["age", "first_name", "last_name"]
|
398
581
|
```
|
399
582
|
|
400
583
|
[⬆️ Back to Top](#table-of-contents-)
|
@@ -412,24 +595,30 @@ But, if you desire except one or more features, use the `Micro::Attributes.witho
|
|
412
595
|
```ruby
|
413
596
|
Micro::Attributes.with(:initialize)
|
414
597
|
|
415
|
-
Micro::Attributes.with(initialize
|
598
|
+
Micro::Attributes.with(:initialize, :keys_as_symbol)
|
599
|
+
|
600
|
+
Micro::Attributes.with(:keys_as_symbol, initialize: :strict)
|
416
601
|
|
417
602
|
Micro::Attributes.with(:diff, :initialize)
|
418
603
|
|
419
604
|
Micro::Attributes.with(:diff, initialize: :strict)
|
420
605
|
|
606
|
+
Micro::Attributes.with(:diff, :keys_as_symbol, initialize: :strict)
|
607
|
+
|
421
608
|
Micro::Attributes.with(:activemodel_validations)
|
422
609
|
|
423
610
|
Micro::Attributes.with(:activemodel_validations, :diff)
|
424
611
|
|
425
612
|
Micro::Attributes.with(:activemodel_validations, :diff, initialize: :strict)
|
613
|
+
|
614
|
+
Micro::Attributes.with(:activemodel_validations, :diff, :keys_as_symbol, initialize: :strict)
|
426
615
|
```
|
427
616
|
|
428
617
|
The method `Micro::Attributes.with()` will raise an exception if no arguments/features were declared.
|
429
618
|
|
430
619
|
```ruby
|
431
620
|
class Job
|
432
|
-
include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: :activemodel_validations, :diff, :initialize)
|
621
|
+
include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: :activemodel_validations, :diff, :initialize, :keys_as_symbol)
|
433
622
|
end
|
434
623
|
```
|
435
624
|
|
@@ -438,15 +627,19 @@ end
|
|
438
627
|
Picking *except* one or more features
|
439
628
|
|
440
629
|
```ruby
|
441
|
-
Micro::Attributes.without(:diff) # will load :activemodel_validations and initialize: :strict
|
630
|
+
Micro::Attributes.without(:diff) # will load :activemodel_validations, :keys_as_symbol and initialize: :strict
|
442
631
|
|
443
|
-
Micro::Attributes.without(initialize: :strict) # will load :activemodel_validations and :
|
632
|
+
Micro::Attributes.without(initialize: :strict) # will load :activemodel_validations, :diff and :keys_as_symbol
|
444
633
|
```
|
445
634
|
|
446
635
|
## Picking all the features
|
447
636
|
|
448
637
|
```ruby
|
449
638
|
Micro::Attributes.with_all_features
|
639
|
+
|
640
|
+
# This method returns the same of:
|
641
|
+
|
642
|
+
Micro::Attributes.with(:activemodel_validations, :diff, :keys_as_symbol, initialize: :strict)
|
450
643
|
```
|
451
644
|
|
452
645
|
[⬆️ Back to Top](#table-of-contents-)
|
@@ -638,6 +831,40 @@ job.state # 'sleeping'
|
|
638
831
|
|
639
832
|
[⬆️ Back to Top](#table-of-contents-)
|
640
833
|
|
834
|
+
### Keys as symbol extension
|
835
|
+
|
836
|
+
Disables the indifferent access requiring the declaration/usage of the attributes as symbols.
|
837
|
+
|
838
|
+
The advantage of this extension over the default behavior is because it avoids an unnecessary allocation in memory of strings. All the keys are transformed into strings in the indifferent access mode, but, with this extension, this typecasting will be avoided. So, it has a better performance and reduces the usage of memory/Garbage collector, but gives for you the responsibility to always use symbols to set/access the attributes.
|
839
|
+
|
840
|
+
```ruby
|
841
|
+
class Job
|
842
|
+
include Micro::Attributes.with(:initialize, :keys_as_symbol)
|
843
|
+
|
844
|
+
attribute :id
|
845
|
+
attribute :state, default: 'sleeping'
|
846
|
+
end
|
847
|
+
|
848
|
+
job = Job.new(id: 1)
|
849
|
+
|
850
|
+
job.attributes # {:id => 1, :state => "sleeping"}
|
851
|
+
|
852
|
+
job.attribute?(:id) # true
|
853
|
+
job.attribute?('id') # false
|
854
|
+
|
855
|
+
job.attribute(:id) # 1
|
856
|
+
job.attribute('id') # nil
|
857
|
+
|
858
|
+
job.attribute!(:id) # 1
|
859
|
+
job.attribute!('id') # NameError (undefined attribute `id)
|
860
|
+
```
|
861
|
+
|
862
|
+
As you could see in the previous example only symbols will work to do something with the attributes.
|
863
|
+
|
864
|
+
This extension also changes the `diff extension` making everything (arguments, outputs) working only with symbols.
|
865
|
+
|
866
|
+
[⬆️ Back to Top](#table-of-contents-)
|
867
|
+
|
641
868
|
# Development
|
642
869
|
|
643
870
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|