u-attributes 2.0.0 → 2.0.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: ac1586077d89b91d2e851ce3f59819d0c474bc809fe9d64eff5d5627bd78a967
4
- data.tar.gz: 7246180e49313f3b9038e3bfdd858356dce65a80c7c94aa6173a15afbea9ab90
3
+ metadata.gz: bc53b00949ac8d0d8d8572443936ba537a637569be77e0b105a0b98f2d1ae9d0
4
+ data.tar.gz: 94f42f6da3c2cba68f6565e1bb413b5692bd700baa077555cd421e4aeb82e2ff
5
5
  SHA512:
6
- metadata.gz: 1ce2864d28e95139a1fc3e3a08ca08ea2c771eec936b5ff21567fb3f0bae792bd406a4b905c7c5346b7f53de3972a6f01ce4629e50e786935186ae6f93614956
7
- data.tar.gz: 28076be013bc9038497297186994d23df2b39b16fb46b2a6c82d59520f3f5de84a3c1f1f89196a6dc073677f0fa339a707e1a2cb10591e9aabfc19dab80036b6
6
+ metadata.gz: e5617a5fd34458de945dae2874bed24013e682871f19b70063e734156f2528e8b249e615632f90c978c203abf876560de9717940f9b81e48271f84a956456199
7
+ data.tar.gz: 50b19483c9e8f88169101306be67a34e4e8c6a26358b187fd119b41ca26e83d461619d6a149bfc898ab7b1208c6af6791b58acf039a3d92d0e8f912e007232b9
data/README.md CHANGED
@@ -1,16 +1,16 @@
1
1
  ![Ruby](https://img.shields.io/badge/ruby-2.2+-ruby.svg?colorA=99004d&colorB=cc0066)
2
2
  [![Gem](https://img.shields.io/gem/v/u-attributes.svg?style=flat-square)](https://rubygems.org/gems/u-attributes)
3
- [![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=master)](https://travis-ci.com/serradura/u-attributes)
3
+ [![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=main)](https://travis-ci.com/serradura/u-attributes)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability)](https://codeclimate.com/github/serradura/u-attributes/maintainability)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage)](https://codeclimate.com/github/serradura/u-attributes/test_coverage)
6
6
 
7
7
  μ-attributes (Micro::Attributes) <!-- omit in toc -->
8
8
  ================================
9
9
 
10
- This gem allows defining read-only attributes, that is, your objects will have only getters to access their attributes data.
10
+ This gem allows you to define "immutable" objects, and your objects will have only getters and no setters.
11
+ 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.
11
12
 
12
13
  ## Table of contents <!-- omit in toc -->
13
- - [Required Ruby version](#required-ruby-version)
14
14
  - [Installation](#installation)
15
15
  - [Compatibility](#compatibility)
16
16
  - [Usage](#usage)
@@ -23,26 +23,27 @@ This gem allows defining read-only attributes, that is, your objects will have o
23
23
  - [`#with_attribute()`](#with_attribute)
24
24
  - [`#with_attributes()`](#with_attributes)
25
25
  - [Defining default values to the attributes](#defining-default-values-to-the-attributes)
26
- - [Strict initializer](#strict-initializer)
26
+ - [The strict initializer](#the-strict-initializer)
27
27
  - [Is it possible to inherit the attributes?](#is-it-possible-to-inherit-the-attributes)
28
- - [.attribute!()](#attribute)
28
+ - [`.attribute!()`](#attribute)
29
29
  - [How to query the attributes?](#how-to-query-the-attributes)
30
30
  - [Built-in extensions](#built-in-extensions)
31
- - [ActiveModel::Validations extension](#activemodelvalidations-extension)
32
- - [Attribute options](#attribute-options)
33
- - [Diff extension](#diff-extension)
34
- - [Initialize extension](#initialize-extension)
35
- - [Strict initialize mode](#strict-initialize-mode)
31
+ - [Picking specific features](#picking-specific-features)
32
+ - [`Micro::Attributes.with`](#microattributeswith)
33
+ - [`Micro::Attributes.without`](#microattributeswithout)
34
+ - [Picking all the features](#picking-all-the-features)
35
+ - [Extensions](#extensions)
36
+ - [`ActiveModel::Validation` extension](#activemodelvalidation-extension)
37
+ - [`.attribute()` options](#attribute-options)
38
+ - [Diff extension](#diff-extension)
39
+ - [Initialize extension](#initialize-extension)
40
+ - [Strict mode](#strict-mode)
36
41
  - [Development](#development)
37
42
  - [Contributing](#contributing)
38
43
  - [License](#license)
39
44
  - [Code of Conduct](#code-of-conduct)
40
45
 
41
- ## Required Ruby version
42
-
43
- > \>= 2.2.0
44
-
45
- ## Installation
46
+ # Installation
46
47
 
47
48
  Add this line to your application's Gemfile and `bundle install`:
48
49
 
@@ -50,16 +51,20 @@ Add this line to your application's Gemfile and `bundle install`:
50
51
  gem 'u-attributes'
51
52
  ```
52
53
 
53
- ## Compatibility
54
+ # Compatibility
54
55
 
55
56
  | u-attributes | branch | ruby | activemodel |
56
57
  | -------------- | ------- | -------- | ------------- |
57
- | 2.0.0 | master | >= 2.2.0 | >= 3.2, < 6.1 |
58
+ | 2.0.0 | main | >= 2.2.0 | >= 3.2, < 6.1 |
58
59
  | 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
59
60
 
60
- ## Usage
61
+ > **Note**: The activemodel is an optional dependency, this module [can be enabled](#activemodelvalidation-extension) to validate the attributes.
62
+
63
+ [⬆️ Back to Top](#table-of-contents-)
61
64
 
62
- ### How to define attributes?
65
+ # Usage
66
+
67
+ ## How to define attributes?
63
68
 
64
69
  ```ruby
65
70
  # By default you must to define the class constructor.
@@ -67,8 +72,8 @@ gem 'u-attributes'
67
72
  class Person
68
73
  include Micro::Attributes
69
74
 
70
- attribute :name
71
75
  attribute :age
76
+ attribute :name
72
77
 
73
78
  def initialize(name: 'John Doe', age:)
74
79
  @name, @age = name, age
@@ -77,8 +82,8 @@ end
77
82
 
78
83
  person = Person.new(age: 21)
79
84
 
80
- person.name # John Doe
81
85
  person.age # 21
86
+ person.name # John Doe
82
87
 
83
88
  # By design the attributes are always exposed as reader methods (getters).
84
89
  # If you try to call a setter you will see a NoMethodError.
@@ -87,7 +92,9 @@ person.age # 21
87
92
  # NoMethodError (undefined method `name=' for #<Person:0x0000... @name='John Doe', @age=21>)
88
93
  ```
89
94
 
90
- #### `Micro::Attributes#attributes=`
95
+ [⬆️ Back to Top](#table-of-contents-)
96
+
97
+ ### `Micro::Attributes#attributes=`
91
98
 
92
99
  This is a protected method to make easier the assignment in a constructor. e.g.
93
100
 
@@ -95,8 +102,8 @@ This is a protected method to make easier the assignment in a constructor. e.g.
95
102
  class Person
96
103
  include Micro::Attributes
97
104
 
98
- attribute :name, default: 'John Doe'
99
105
  attribute :age
106
+ attribute :name, default: 'John Doe'
100
107
 
101
108
  def initialize(options)
102
109
  self.attributes = options
@@ -105,19 +112,21 @@ end
105
112
 
106
113
  person = Person.new(age: 20)
107
114
 
108
- person.name # John Doe
109
115
  person.age # 20
116
+ person.name # John Doe
110
117
  ```
111
118
 
112
- #### `Micro::Attributes#attribute`
119
+ [⬆️ Back to Top](#table-of-contents-)
120
+
121
+ ### `Micro::Attributes#attribute`
113
122
 
114
123
  Use this method with a valid attribute name to get its value.
115
124
 
116
125
  ```ruby
117
126
  person = Person.new(age: 20)
118
127
 
119
- person.attribute(:name) # John Doe
120
128
  person.attribute('age') # 20
129
+ person.attribute(:name) # John Doe
121
130
  person.attribute('foo') # nil
122
131
  ```
123
132
 
@@ -129,17 +138,21 @@ person.attribute('age') { |value| puts value } # 20
129
138
  person.attribute('foo') { |value| puts value } # !! Nothing happened, because of the attribute doesn't exist.
130
139
  ```
131
140
 
132
- #### `Micro::Attributes#attribute!`
141
+ [⬆️ Back to Top](#table-of-contents-)
142
+
143
+ ### `Micro::Attributes#attribute!`
133
144
 
134
145
  Works like the `#attribute` method, but it will raise an exception when the attribute doesn't exist.
135
146
 
136
147
  ```ruby
137
- person.attribute!('foo') # NameError (undefined attribute `foo)
148
+ person.attribute!('foo') # NameError (undefined attribute `foo)
138
149
 
139
150
  person.attribute!('foo') { |value| value } # NameError (undefined attribute `foo)
140
151
  ```
141
152
 
142
- ### How to define multiple attributes?
153
+ [⬆️ Back to Top](#table-of-contents-)
154
+
155
+ ## How to define multiple attributes?
143
156
 
144
157
  Use `.attributes` with a list of attribute names.
145
158
 
@@ -162,7 +175,9 @@ person.age # 32
162
175
 
163
176
  > **Note:** This method can't define default values. To do this, use the `#attribute()` method.
164
177
 
165
- ### `Micro::Attributes.with(:initialize)`
178
+ [⬆️ Back to Top](#table-of-contents-)
179
+
180
+ ## `Micro::Attributes.with(:initialize)`
166
181
 
167
182
  Use `Micro::Attributes.with(:initialize)` to define a constructor to assign the attributes. e.g.
168
183
 
@@ -176,41 +191,43 @@ end
176
191
 
177
192
  person = Person.new(age: 18)
178
193
 
179
- person.name # John Doe
180
194
  person.age # 18
195
+ person.name # John Doe
181
196
  ```
182
197
 
183
198
  This extension enables two methods for your objects.
184
199
  The `#with_attribute()` and `#with_attributes()`.
185
200
 
186
- #### `#with_attribute()`
201
+ ### `#with_attribute()`
187
202
 
188
203
  ```ruby
189
204
  another_person = person.with_attribute(:age, 21)
190
205
 
191
- another_person.name # John Doe
192
206
  another_person.age # 21
207
+ another_person.name # John Doe
193
208
  another_person.equal?(person) # false
194
209
  ```
195
210
 
196
- #### `#with_attributes()`
211
+ ### `#with_attributes()`
197
212
 
198
213
  Use it to assign multiple attributes
199
214
  ```ruby
200
215
  other_person = person.with_attributes(name: 'Serradura', age: 32)
201
216
 
202
- other_person.name # Serradura
203
217
  other_person.age # 32
218
+ other_person.name # Serradura
204
219
  other_person.equal?(person) # false
205
220
  ```
206
221
 
207
222
  If you pass a value different of a Hash, a Kind::Error will be raised.
208
223
 
209
224
  ```ruby
210
- Person.new(1) # Kind::Error (1 must be a Hash)
225
+ Person.new(1) # Kind::Error (1 expected to be a kind of Hash)
211
226
  ```
212
227
 
213
- ### Defining default values to the attributes
228
+ [⬆️ Back to Top](#table-of-contents-)
229
+
230
+ ## Defining default values to the attributes
214
231
 
215
232
  To do this, you only need make use of the `default:` keyword. e.g.
216
233
 
@@ -237,7 +254,9 @@ class Person
237
254
  end
238
255
  ```
239
256
 
240
- ### Strict initializer
257
+ [⬆️ Back to Top](#table-of-contents-)
258
+
259
+ ## The strict initializer
241
260
 
242
261
  Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords. e.g.
243
262
 
@@ -257,13 +276,15 @@ An attribute with a default value can be omitted.
257
276
  ``` ruby
258
277
  person_without_age = StrictPerson.new(age: nil)
259
278
 
260
- person_without_age.name # 'John Doe'
261
279
  person_without_age.age # nil
280
+ person_without_age.name # 'John Doe'
262
281
  ```
263
282
 
264
283
  > **Note:** Except for this validation the `.with(initialize: :strict)` method will works in the same ways of `.with(:initialize)`.
265
284
 
266
- ### Is it possible to inherit the attributes?
285
+ [⬆️ Back to Top](#table-of-contents-)
286
+
287
+ ## Is it possible to inherit the attributes?
267
288
 
268
289
  Yes. e.g.
269
290
 
@@ -286,7 +307,9 @@ instance.respond_to?(:age) # true
286
307
  instance.respond_to?(:foo) # true
287
308
  ```
288
309
 
289
- #### .attribute!()
310
+ [⬆️ Back to Top](#table-of-contents-)
311
+
312
+ ### `.attribute!()`
290
313
 
291
314
  This method allows us to redefine the attributes default data that was defined in the parent class. e.g.
292
315
 
@@ -311,7 +334,9 @@ beta_person.name # 'Beta'
311
334
  beta_person.age # 0
312
335
  ```
313
336
 
314
- ### How to query the attributes?
337
+ [⬆️ Back to Top](#table-of-contents-)
338
+
339
+ ## How to query the attributes?
315
340
 
316
341
  ```ruby
317
342
  class Person
@@ -372,76 +397,65 @@ person.attributes(:age, :name) # {age: 20, name: 'John Doe'}
372
397
  person.attributes('age', 'name') # {'age'=>20, 'name'=>'John Doe'}
373
398
  ```
374
399
 
375
- ## Built-in extensions
400
+ [⬆️ Back to Top](#table-of-contents-)
401
+
402
+ # Built-in extensions
376
403
 
377
404
  You can use the method `Micro::Attributes.with()` to combine and require only the features that better fit your needs.
378
405
 
379
406
  But, if you desire except one or more features, use the `Micro::Attributes.without()` method.
380
407
 
408
+ ## Picking specific features
409
+
410
+ ### `Micro::Attributes.with`
411
+
381
412
  ```ruby
382
- #===========================#
383
- # Loading specific features #
384
- #===========================#
413
+ Micro::Attributes.with(:initialize)
385
414
 
386
- class Job
387
- include Micro::Attributes.with(:diff)
415
+ Micro::Attributes.with(initialize: :strict)
388
416
 
389
- attribute :id
390
- attribute :state, default: 'sleeping'
417
+ Micro::Attributes.with(:diff, :initialize)
391
418
 
392
- def initialize(options)
393
- self.attributes = options
394
- end
395
- end
419
+ Micro::Attributes.with(:diff, initialize: :strict)
396
420
 
397
- #======================#
398
- # Loading all features #
399
- # --- #
400
- #======================#
421
+ Micro::Attributes.with(:activemodel_validations)
401
422
 
402
- class Job
403
- include Micro::Attributes.with_all_features
423
+ Micro::Attributes.with(:activemodel_validations, :diff)
404
424
 
405
- attribute :id
406
- attribute :state, default: 'sleeping'
407
- end
425
+ Micro::Attributes.with(:activemodel_validations, :diff, initialize: :strict)
426
+ ```
408
427
 
409
- #----------------------------------------------------------------------------#
410
- # Using the .with() method alias and adding the strict initialize extension. #
411
- #----------------------------------------------------------------------------#
412
- class Job
413
- include Micro::Attributes.with(:diff, initialize: :strict)
428
+ The method `Micro::Attributes.with()` will raise an exception if no arguments/features were declared.
414
429
 
415
- attribute :id
416
- attribute :state, default: 'sleeping'
430
+ ```ruby
431
+ class Job
432
+ include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: :activemodel_validations, :diff, :initialize)
417
433
  end
434
+ ```
418
435
 
419
- # Note:
420
- # The method `Micro::Attributes.with()` will raise an exception if no arguments/features were declared.
421
- #
422
- # class Job
423
- # include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: diff, initialize, activemodel_validations)
424
- # end
436
+ ### `Micro::Attributes.without`
425
437
 
426
- #=====================================#
427
- # Loading except one or more features #
428
- # ----- #
429
- #=====================================#
438
+ Picking *except* one or more features
430
439
 
431
- class Job
432
- include Micro::Attributes.without(:diff)
440
+ ```ruby
441
+ Micro::Attributes.without(:diff) # will load :activemodel_validations and initialize: :strict
433
442
 
434
- attribute :id
435
- attribute :state, default: 'sleeping'
436
- end
443
+ Micro::Attributes.without(initialize: :strict) # will load :activemodel_validations and :diff
444
+ ```
437
445
 
438
- # Note:
439
- # The method `Micro::Attributes.without()` returns `Micro::Attributes` if all features extensions were used.
446
+ ## Picking all the features
447
+
448
+ ```ruby
449
+ Micro::Attributes.with_all_features
440
450
  ```
441
451
 
442
- ### ActiveModel::Validations extension
452
+ [⬆️ Back to Top](#table-of-contents-)
453
+
454
+ ## Extensions
455
+
456
+ ### `ActiveModel::Validation` extension
443
457
 
444
- If your application uses ActiveModel as a dependency (like a regular Rails app). You will be enabled to use the `actimodel_validations` extension.
458
+ If your application uses ActiveModel as a dependency (like a regular Rails app). You will be enabled to use the `activemodel_validations` extension.
445
459
 
446
460
  ```ruby
447
461
  class Job
@@ -461,7 +475,7 @@ job.id # 1
461
475
  job.state # 'sleeping'
462
476
  ```
463
477
 
464
- #### Attribute options
478
+ #### `.attribute()` options
465
479
 
466
480
  You can use the `validate` or `validates` options to define your attributes. e.g.
467
481
 
@@ -472,7 +486,7 @@ class Job
472
486
  attribute :id, validates: { presence: true }
473
487
  attribute :state, validate: :must_be_a_filled_string
474
488
 
475
- def must_be_a_string
489
+ def must_be_a_filled_string
476
490
  return if state.is_a?(String) && state.present?
477
491
 
478
492
  errors.add(:state, 'must be a filled string')
@@ -480,6 +494,8 @@ class Job
480
494
  end
481
495
  ```
482
496
 
497
+ [⬆️ Back to Top](#table-of-contents-)
498
+
483
499
  ### Diff extension
484
500
 
485
501
  Provides a way to track changes in your object attributes.
@@ -529,6 +545,8 @@ job_changes.changed?(:state, from: 'sleeping', to: 'running') # true
529
545
  job_changes.differences # {'state'=> {'from' => 'sleeping', 'to' => 'running'}}
530
546
  ```
531
547
 
548
+ [⬆️ Back to Top](#table-of-contents-)
549
+
532
550
  ### Initialize extension
533
551
 
534
552
  1. Creates a constructor to assign the attributes.
@@ -578,7 +596,9 @@ other_job.state # killed
578
596
  other_job.equal?(job) # false
579
597
  ```
580
598
 
581
- ### Strict initialize mode
599
+ [⬆️ Back to Top](#table-of-contents-)
600
+
601
+ #### Strict mode
582
602
 
583
603
  1. Creates a constructor to assign the attributes.
584
604
  2. Adds methods to build new instances when some data was assigned.
@@ -616,20 +636,22 @@ job.state # 'sleeping'
616
636
 
617
637
  > **Note**: This extension works like the `initialize` extension. So, look at its section to understand all of the other features.
618
638
 
619
- ## Development
639
+ [⬆️ Back to Top](#table-of-contents-)
640
+
641
+ # Development
620
642
 
621
643
  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.
622
644
 
623
645
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
624
646
 
625
- ## Contributing
647
+ # Contributing
626
648
 
627
649
  Bug reports and pull requests are welcome on GitHub at https://github.com/serradura/u-attributes. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
628
650
 
629
- ## License
651
+ # License
630
652
 
631
653
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
632
654
 
633
- ## Code of Conduct
655
+ # Code of Conduct
634
656
 
635
- Everyone interacting in the Micro::Attributes project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/serradura/u-attributes/blob/master/CODE_OF_CONDUCT.md).
657
+ Everyone interacting in the Micro::Attributes project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/serradura/u-attributes/blob/main/CODE_OF_CONDUCT.md).
@@ -89,7 +89,7 @@ module Micro
89
89
  callable = default.is_a?(Proc) ? default : default.method(:call)
90
90
  callable.arity > 0 ? callable.call(value) : callable.call
91
91
  else
92
- value || default
92
+ value.nil? ? default : value
93
93
  end
94
94
 
95
95
  __attribute_set(key, final_value)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Micro
4
4
  module Attributes
5
- VERSION = '2.0.0'.freeze
5
+ VERSION = '2.0.1'.freeze
6
6
  end
7
7
  end
@@ -9,8 +9,11 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Rodrigo Serradura']
10
10
  spec.email = ['rodrigo.serradura@gmail.com']
11
11
 
12
- spec.summary = %q{Define read-only attributes}
13
- spec.description = %q{This gem allows defining read-only attributes, that is, your objects will have only getters to access their attributes data.}
12
+ spec.summary = %q{Create "immutable" objects. No setters, just getters!}
13
+ spec.description =
14
+ "This gem allows you to define \"immutable\" objects, and your objects will have only getters and no setters. "\
15
+ "So, if you change some object attribute, you will have a new object instance. " \
16
+ "That is, you transform the object instead of modifying it."
14
17
  spec.homepage = 'https://github.com/serradura/u-attributes'
15
18
  spec.license = 'MIT'
16
19
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u-attributes
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Serradura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-20 00:00:00.000000000 Z
11
+ date: 2020-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kind
@@ -58,8 +58,10 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '13.0'
61
- description: This gem allows defining read-only attributes, that is, your objects
62
- will have only getters to access their attributes data.
61
+ description: This gem allows you to define "immutable" objects, and your objects will
62
+ have only getters and no setters. So, if you change some object attribute, you will
63
+ have a new object instance. That is, you transform the object instead of modifying
64
+ it.
63
65
  email:
64
66
  - rodrigo.serradura@gmail.com
65
67
  executables: []
@@ -112,5 +114,5 @@ requirements: []
112
114
  rubygems_version: 3.0.6
113
115
  signing_key:
114
116
  specification_version: 4
115
- summary: Define read-only attributes
117
+ summary: Create "immutable" objects. No setters, just getters!
116
118
  test_files: []