u-attributes 2.0.0 → 2.0.1

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: 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: []