u-attributes 1.2.0 → 2.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: 97dfa238f3a4bbeea816dd6965e9261de6cff2af2c14a5934c9d2ffdee03b2a4
4
- data.tar.gz: a21fb9c6247d7d8b6969c0f60539dfe9e5bec6fb502c945dea64ec8534a86265
3
+ metadata.gz: ac1586077d89b91d2e851ce3f59819d0c474bc809fe9d64eff5d5627bd78a967
4
+ data.tar.gz: 7246180e49313f3b9038e3bfdd858356dce65a80c7c94aa6173a15afbea9ab90
5
5
  SHA512:
6
- metadata.gz: a99ea97d70785cfa6f90a3a638ca4fe68bffc2ee05d4b3d9f5a3b9b31de2c3076607f1c64753c1c3850df6150d105985a5336b2d66e0560dab77ceea35a12b28
7
- data.tar.gz: daaee31a1f10ec4c74ffc59131196f040ce33eee787ea0381643737ade568615d1b52c78964a392f8e41a476de940d5b0a215102537514783273dd79da0329f1
6
+ metadata.gz: 1ce2864d28e95139a1fc3e3a08ca08ea2c771eec936b5ff21567fb3f0bae792bd406a4b905c7c5346b7f53de3972a6f01ce4629e50e786935186ae6f93614956
7
+ data.tar.gz: 28076be013bc9038497297186994d23df2b39b16fb46b2a6c82d59520f3f5de84a3c1f1f89196a6dc073677f0fa339a707e1a2cb10591e9aabfc19dab80036b6
data/.gitignore CHANGED
@@ -6,3 +6,4 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ Gemfile.lock
data/.travis.sh CHANGED
@@ -20,5 +20,12 @@ ACTIVEMODEL_VERSION='5.0' bundle exec rake test
20
20
  ACTIVEMODEL_VERSION='5.1' bundle update
21
21
  ACTIVEMODEL_VERSION='5.1' bundle exec rake test
22
22
 
23
- ACTIVEMODEL_VERSION='5.2' bundle update
24
- ACTIVEMODEL_VERSION='5.2' bundle exec rake test
23
+ if [[ ! $ruby_v =~ '2.2.0' ]]; then
24
+ ACTIVEMODEL_VERSION='5.2' bundle update
25
+ ACTIVEMODEL_VERSION='5.2' bundle exec rake test
26
+ fi
27
+
28
+ if [[ $ruby_v =~ '2.5.' ]] || [[ $ruby_v =~ '2.6.' ]] || [[ $ruby_v =~ '2.7.' ]]; then
29
+ ACTIVEMODEL_VERSION='6.0' bundle update
30
+ ACTIVEMODEL_VERSION='6.0' bundle exec rake test
31
+ fi
@@ -8,6 +8,7 @@ rvm:
8
8
  - 2.4.0
9
9
  - 2.5.0
10
10
  - 2.6.0
11
+ - 2.7.0
11
12
 
12
13
  cache: bundler
13
14
 
@@ -20,9 +21,9 @@ install: bundle install --jobs=3 --retry=3
20
21
  before_script:
21
22
  - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
22
23
  - chmod +x ./cc-test-reporter
23
- - "./cc-test-reporter before-build"
24
+ - './cc-test-reporter before-build'
24
25
 
25
- script: "./.travis.sh"
26
+ script: './.travis.sh'
26
27
 
27
28
  after_success:
28
- - "./cc-test-reporter after-build -t simplecov"
29
+ - './cc-test-reporter after-build -t simplecov'
data/Gemfile CHANGED
@@ -10,7 +10,7 @@ activemodel = case activemodel_version
10
10
  when '5.0' then '5.0.7'
11
11
  when '5.1' then '5.1.7'
12
12
  when '5.2' then '5.2.3'
13
- when '6.0' then '6.0.0.rc1'
13
+ when '6.0' then '6.0.0'
14
14
  end
15
15
 
16
16
  if activemodel_version < '6.1'
@@ -3,7 +3,7 @@ The MIT License (MIT)
3
3
  Copyright (c) 2019 Rodrigo Serradura
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
6
+ of this software and associated documentation files (the 'Software'), to deal
7
7
  in the Software without restriction, including without limitation the rights
8
8
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
9
  copies of the Software, and to permit persons to whom the Software is
@@ -12,7 +12,7 @@ furnished to do so, subject to the following conditions:
12
12
  The above copyright notice and this permission notice shall be included in
13
13
  all copies or substantial portions of the Software.
14
14
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
16
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
17
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
data/README.md CHANGED
@@ -1,34 +1,42 @@
1
+ ![Ruby](https://img.shields.io/badge/ruby-2.2+-ruby.svg?colorA=99004d&colorB=cc0066)
1
2
  [![Gem](https://img.shields.io/gem/v/u-attributes.svg?style=flat-square)](https://rubygems.org/gems/u-attributes)
2
3
  [![Build Status](https://travis-ci.com/serradura/u-attributes.svg?branch=master)](https://travis-ci.com/serradura/u-attributes)
3
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/maintainability)](https://codeclimate.com/github/serradura/u-attributes/maintainability)
4
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/b562e6b877a9edf4dbf6/test_coverage)](https://codeclimate.com/github/serradura/u-attributes/test_coverage)
5
6
 
6
- μ-attributes (Micro::Attributes)
7
+ μ-attributes (Micro::Attributes) <!-- omit in toc -->
7
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
11
 
11
- ## Table of contents
12
- - [μ-attributes (Micro::Attributes)](#%ce%bc-attributes-microattributes)
13
- - [Table of contents](#table-of-contents)
14
- - [Required Ruby version](#required-ruby-version)
15
- - [Installation](#installation)
16
- - [Usage](#usage)
17
- - [How to require?](#how-to-require)
18
- - [How to define attributes?](#how-to-define-attributes)
19
- - [How to define multiple attributes?](#how-to-define-multiple-attributes)
20
- - [How to define attributes with a constructor to assign them?](#how-to-define-attributes-with-a-constructor-to-assign-them)
21
- - [How to inherit the attributes?](#how-to-inherit-the-attributes)
22
- - [How to query the attributes?](#how-to-query-the-attributes)
23
- - [Built-in extensions](#built-in-extensions)
24
- - [ActiveModel::Validations extension](#activemodelvalidations-extension)
25
- - [Diff extension](#diff-extension)
26
- - [Initialize extension](#initialize-extension)
27
- - [Strict initialize extension](#strict-initialize-extension)
28
- - [Development](#development)
29
- - [Contributing](#contributing)
30
- - [License](#license)
31
- - [Code of Conduct](#code-of-conduct)
12
+ ## Table of contents <!-- omit in toc -->
13
+ - [Required Ruby version](#required-ruby-version)
14
+ - [Installation](#installation)
15
+ - [Compatibility](#compatibility)
16
+ - [Usage](#usage)
17
+ - [How to define attributes?](#how-to-define-attributes)
18
+ - [`Micro::Attributes#attributes=`](#microattributesattributes)
19
+ - [`Micro::Attributes#attribute`](#microattributesattribute)
20
+ - [`Micro::Attributes#attribute!`](#microattributesattribute-1)
21
+ - [How to define multiple attributes?](#how-to-define-multiple-attributes)
22
+ - [`Micro::Attributes.with(:initialize)`](#microattributeswithinitialize)
23
+ - [`#with_attribute()`](#with_attribute)
24
+ - [`#with_attributes()`](#with_attributes)
25
+ - [Defining default values to the attributes](#defining-default-values-to-the-attributes)
26
+ - [Strict initializer](#strict-initializer)
27
+ - [Is it possible to inherit the attributes?](#is-it-possible-to-inherit-the-attributes)
28
+ - [.attribute!()](#attribute)
29
+ - [How to query the attributes?](#how-to-query-the-attributes)
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)
36
+ - [Development](#development)
37
+ - [Contributing](#contributing)
38
+ - [License](#license)
39
+ - [Code of Conduct](#code-of-conduct)
32
40
 
33
41
  ## Required Ruby version
34
42
 
@@ -36,37 +44,24 @@ This gem allows defining read-only attributes, that is, your objects will have o
36
44
 
37
45
  ## Installation
38
46
 
39
- Add this line to your application's Gemfile:
47
+ Add this line to your application's Gemfile and `bundle install`:
40
48
 
41
49
  ```ruby
42
50
  gem 'u-attributes'
43
51
  ```
44
52
 
45
- And then execute:
53
+ ## Compatibility
46
54
 
47
- $ bundle
48
-
49
- Or install it yourself as:
50
-
51
- $ gem install u-attributes
55
+ | u-attributes | branch | ruby | activemodel |
56
+ | -------------- | ------- | -------- | ------------- |
57
+ | 2.0.0 | master | >= 2.2.0 | >= 3.2, < 6.1 |
58
+ | 1.2.0 | v1.x | >= 2.2.0 | >= 3.2, < 6.1 |
52
59
 
53
60
  ## Usage
54
61
 
55
- ### How to require?
56
- ```ruby
57
- # Bundler will do it automatically, but if you desire to do a manual require.
58
- # Use one of the following options:
59
-
60
- require 'micro/attributes'
61
-
62
- # or
63
-
64
- require 'u-attributes'
65
- ```
66
-
67
62
  ### How to define attributes?
68
- ```ruby
69
63
 
64
+ ```ruby
70
65
  # By default you must to define the class constructor.
71
66
 
72
67
  class Person
@@ -82,25 +77,25 @@ end
82
77
 
83
78
  person = Person.new(age: 21)
84
79
 
85
- puts person.name # John Doe
86
- puts person.age # 21
80
+ person.name # John Doe
81
+ person.age # 21
87
82
 
88
- # By design, the attributes expose only reader methods (getters).
89
- # If you try to call a setter, you will see a NoMethodError.
83
+ # By design the attributes are always exposed as reader methods (getters).
84
+ # If you try to call a setter you will see a NoMethodError.
90
85
  #
91
86
  # person.name = 'Rodrigo'
92
- # NoMethodError (undefined method `name=' for #<Person:0x0000... @name="John Doe", @age=21>)
87
+ # NoMethodError (undefined method `name=' for #<Person:0x0000... @name='John Doe', @age=21>)
88
+ ```
93
89
 
94
- #------------------#
95
- # self.attributes= #
96
- #------------------#
90
+ #### `Micro::Attributes#attributes=`
97
91
 
98
- # This protected method is added to make easier the assignment in a constructor.
92
+ This is a protected method to make easier the assignment in a constructor. e.g.
99
93
 
94
+ ```ruby
100
95
  class Person
101
96
  include Micro::Attributes
102
97
 
103
- attribute :name, 'John Doe' # .attribute() accepts a second arg as its default value
98
+ attribute :name, default: 'John Doe'
104
99
  attribute :age
105
100
 
106
101
  def initialize(options)
@@ -110,46 +105,49 @@ end
110
105
 
111
106
  person = Person.new(age: 20)
112
107
 
113
- puts person.name # John Doe
114
- puts person.age # 20
108
+ person.name # John Doe
109
+ person.age # 20
110
+ ```
115
111
 
116
- #--------------#
117
- # #attribute() #
118
- #--------------#
119
- #
120
- # Use the #attribute() method with a valid attribute name to get its value
112
+ #### `Micro::Attributes#attribute`
121
113
 
122
- puts person.attribute(:name) # John Doe
123
- puts person.attribute('age') # 20
124
- puts person.attribute('foo') # nil
114
+ Use this method with a valid attribute name to get its value.
125
115
 
126
- #
127
- # If you pass a block, it will be executed only if the attribute is valid.
116
+ ```ruby
117
+ person = Person.new(age: 20)
118
+
119
+ person.attribute(:name) # John Doe
120
+ person.attribute('age') # 20
121
+ person.attribute('foo') # nil
122
+ ```
128
123
 
124
+ If you pass a block, it will be executed only if the attribute was valid.
125
+
126
+ ```ruby
129
127
  person.attribute(:name) { |value| puts value } # John Doe
130
128
  person.attribute('age') { |value| puts value } # 20
131
- person.attribute('foo') { |value| puts value } # !! Nothing happened, because of the attribute not exists.
129
+ person.attribute('foo') { |value| puts value } # !! Nothing happened, because of the attribute doesn't exist.
130
+ ```
132
131
 
133
- #---------------#
134
- # #attribute!() #
135
- #---------------#
136
- #
137
- # Works like the #attribute() method, but will raise an exception when the attribute not exist.
132
+ #### `Micro::Attributes#attribute!`
138
133
 
139
- puts person.attribute!('foo') # NameError (undefined attribute `foo)
140
- person.attribute!('foo') { |value| puts value } # NameError (undefined attribute `foo)
134
+ Works like the `#attribute` method, but it will raise an exception when the attribute doesn't exist.
135
+
136
+ ```ruby
137
+ person.attribute!('foo') # NameError (undefined attribute `foo)
138
+
139
+ person.attribute!('foo') { |value| value } # NameError (undefined attribute `foo)
141
140
  ```
142
141
 
143
142
  ### How to define multiple attributes?
144
143
 
145
- ```ruby
146
-
147
- # Use .attributes with a list of attribute names.
144
+ Use `.attributes` with a list of attribute names.
148
145
 
146
+ ```ruby
149
147
  class Person
150
148
  include Micro::Attributes
151
149
 
152
- attributes :age, name: 'John Doe' # Use a hash to define attributes with default values
150
+ attributes :age, :name
153
151
 
154
152
  def initialize(options)
155
153
  self.attributes = options
@@ -158,89 +156,123 @@ end
158
156
 
159
157
  person = Person.new(age: 32)
160
158
 
161
- puts person.name # 'John Doe'
162
- puts person.age # 32
159
+ person.name # nil
160
+ person.age # 32
163
161
  ```
164
162
 
165
- ### How to define attributes with a constructor to assign them?
166
- A: Use `Micro::Attributes.to_initialize`
163
+ > **Note:** This method can't define default values. To do this, use the `#attribute()` method.
164
+
165
+ ### `Micro::Attributes.with(:initialize)`
166
+
167
+ Use `Micro::Attributes.with(:initialize)` to define a constructor to assign the attributes. e.g.
167
168
 
168
169
  ```ruby
169
170
  class Person
170
- include Micro::Attributes.to_initialize
171
+ include Micro::Attributes.with(:initialize)
171
172
 
172
- attributes :age, name: 'John Doe'
173
+ attribute :age
174
+ attribute :name, default: 'John Doe'
173
175
  end
174
176
 
175
177
  person = Person.new(age: 18)
176
178
 
177
- puts person.name # John Doe
178
- puts person.age # 18
179
+ person.name # John Doe
180
+ person.age # 18
181
+ ```
179
182
 
180
- ##############################################
181
- # Assigning new values to get a new instance #
182
- ##############################################
183
+ This extension enables two methods for your objects.
184
+ The `#with_attribute()` and `#with_attributes()`.
183
185
 
184
- #-------------------#
185
- # #with_attribute() #
186
- #-------------------#
186
+ #### `#with_attribute()`
187
187
 
188
+ ```ruby
188
189
  another_person = person.with_attribute(:age, 21)
189
190
 
190
- puts another_person.name # John Doe
191
- puts another_person.age # 21
192
- puts another_person.equal?(person) # false
191
+ another_person.name # John Doe
192
+ another_person.age # 21
193
+ another_person.equal?(person) # false
194
+ ```
193
195
 
194
- #--------------------#
195
- # #with_attributes() #
196
- #--------------------#
197
- #
198
- # Use it to assign multiple attributes
196
+ #### `#with_attributes()`
199
197
 
198
+ Use it to assign multiple attributes
199
+ ```ruby
200
200
  other_person = person.with_attributes(name: 'Serradura', age: 32)
201
201
 
202
- puts other_person.name # Serradura
203
- puts other_person.age # 32
204
- puts other_person.equal?(person) # false
202
+ other_person.name # Serradura
203
+ other_person.age # 32
204
+ other_person.equal?(person) # false
205
+ ```
205
206
 
206
- # If you pass a value different of a Hash, an ArgumentError will be raised.
207
- #
208
- # Person.new(1)
209
- # ArgumentError (argument must be a Hash)
207
+ If you pass a value different of a Hash, a Kind::Error will be raised.
210
208
 
211
- #--------------------#
212
- # Strict initializer #
213
- #--------------------#
209
+ ```ruby
210
+ Person.new(1) # Kind::Error (1 must be a Hash)
211
+ ```
212
+
213
+ ### Defining default values to the attributes
214
+
215
+ To do this, you only need make use of the `default:` keyword. e.g.
216
+
217
+ ```ruby
218
+ class Person
219
+ include Micro::Attributes.with(:initialize)
220
+
221
+ attribute :age
222
+ attribute :name, default: 'John Doe'
223
+ end
224
+ ```
225
+
226
+ There are 3 different strategies to define default values.
227
+ 1. Pass a regular object, like in the previous example.
228
+ 2. Pass a `proc`/`lambda`, and if it has an argument you will receive the attribute value to do something before assign it.
229
+ 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`).
214
230
 
215
- # Use .to_initialize! to forbids an instantiation without all keywords.
231
+ ```ruby
232
+ class Person
233
+ include Micro::Attributes.with(:initialize)
216
234
 
235
+ attribute :age, default: -> age { age&.to_i }
236
+ attribute :name, default: -> name { String(name || 'John Doe').strip }
237
+ end
238
+ ```
239
+
240
+ ### Strict initializer
241
+
242
+ Use `.with(initialize: :strict)` to forbids an instantiation without all the attribute keywords. e.g.
243
+
244
+ ```ruby
217
245
  class StrictPerson
218
- include Micro::Attributes.to_initialize!
246
+ include Micro::Attributes.with(initialize: :strict)
219
247
 
220
- attributes :age, name: 'John Doe'
248
+ attribute :age
249
+ attribute :name, default: 'John Doe'
221
250
  end
222
251
 
223
- StrictPerson.new({})
252
+ StrictPerson.new({}) # ArgumentError (missing keyword: :age)
253
+ ```
224
254
 
225
- # The code above will raise:
226
- # ArgumentError (missing keyword: :age)
255
+ An attribute with a default value can be omitted.
227
256
 
257
+ ``` ruby
228
258
  person_without_age = StrictPerson.new(age: nil)
229
259
 
230
- p person_without_age.name # "John Doe"
231
- p person_without_age.age # nil
232
-
233
- # Except for this validation when initializing,
234
- # the `to_initialize!` method will works in the same ways of `to_initialize`.
260
+ person_without_age.name # 'John Doe'
261
+ person_without_age.age # nil
235
262
  ```
236
263
 
237
- ### How to inherit the attributes?
264
+ > **Note:** Except for this validation the `.with(initialize: :strict)` method will works in the same ways of `.with(:initialize)`.
265
+
266
+ ### Is it possible to inherit the attributes?
267
+
268
+ Yes. e.g.
238
269
 
239
270
  ```ruby
240
271
  class Person
241
- include Micro::Attributes.to_initialize
272
+ include Micro::Attributes.with(:initialize)
242
273
 
243
- attributes :age, name: 'John Doe'
274
+ attribute :age
275
+ attribute :name, default: 'John Doe'
244
276
  end
245
277
 
246
278
  class Subclass < Person # Will preserve the parent class attributes
@@ -249,33 +281,34 @@ end
249
281
 
250
282
  instance = Subclass.new({})
251
283
 
252
- puts instance.name # John Doe
253
- puts instance.respond_to?(:age) # true
254
- puts instance.respond_to?(:foo) # true
284
+ instance.name # John Doe
285
+ instance.respond_to?(:age) # true
286
+ instance.respond_to?(:foo) # true
287
+ ```
255
288
 
256
- #---------------------------------#
257
- # .attribute!() or .attributes!() #
258
- #---------------------------------#
289
+ #### .attribute!()
259
290
 
260
- # The methods above allow redefining the attributes default data
291
+ This method allows us to redefine the attributes default data that was defined in the parent class. e.g.
261
292
 
293
+ ```ruby
262
294
  class AnotherSubclass < Person
263
- attribute! :name, 'Alfa'
295
+ attribute! :name, default: 'Alfa'
264
296
  end
265
297
 
266
298
  alfa_person = AnotherSubclass.new({})
267
299
 
268
- p alfa_person.name # "Alfa"
269
- p alfa_person.age # nil
300
+ alfa_person.name # 'Alfa'
301
+ alfa_person.age # nil
270
302
 
271
303
  class SubSubclass < Subclass
272
- attributes! name: 'Beta', age: 0
304
+ attribute! :age, default: 0
305
+ attribute! :name, default: 'Beta'
273
306
  end
274
307
 
275
308
  beta_person = SubSubclass.new({})
276
309
 
277
- p beta_person.name # "Beta"
278
- p beta_person.age # 0
310
+ beta_person.name # 'Beta'
311
+ beta_person.age # 0
279
312
  ```
280
313
 
281
314
  ### How to query the attributes?
@@ -284,7 +317,8 @@ p beta_person.age # 0
284
317
  class Person
285
318
  include Micro::Attributes
286
319
 
287
- attributes :age, name: 'John Doe'
320
+ attribute :age
321
+ attribute :name, default: 'John Doe'
288
322
 
289
323
  def initialize(options)
290
324
  self.attributes = options
@@ -295,16 +329,16 @@ end
295
329
  # .attributes() #
296
330
  #---------------#
297
331
 
298
- p Person.attributes # ["name", "age"]
332
+ Person.attributes # ['name', 'age']
299
333
 
300
334
  #---------------#
301
335
  # .attribute?() #
302
336
  #---------------#
303
337
 
304
- puts Person.attribute?(:name) # true
305
- puts Person.attribute?('name') # true
306
- puts Person.attribute?('foo') # false
307
- puts Person.attribute?(:foo) # false
338
+ Person.attribute?(:name) # true
339
+ Person.attribute?('name') # true
340
+ Person.attribute?('foo') # false
341
+ Person.attribute?(:foo) # false
308
342
 
309
343
  # ---
310
344
 
@@ -314,17 +348,17 @@ person = Person.new(age: 20)
314
348
  # #attribute?() #
315
349
  #---------------#
316
350
 
317
- puts person.attribute?(:name) # true
318
- puts person.attribute?('name') # true
319
- puts person.attribute?('foo') # false
320
- puts person.attribute?(:foo) # false
351
+ person.attribute?(:name) # true
352
+ person.attribute?('name') # true
353
+ person.attribute?('foo') # false
354
+ person.attribute?(:foo) # false
321
355
 
322
356
  #---------------#
323
357
  # #attributes() #
324
358
  #---------------#
325
359
 
326
- p person.attributes # {"age"=>20, "name"=>"John Doe"}
327
- p Person.new(name: 'John').attributes # {"age"=>nil, "name"=>"John"}
360
+ person.attributes # {'age'=>20, 'name'=>'John Doe'}
361
+ Person.new(name: 'John').attributes # {'age'=>nil, 'name'=>'John'}
328
362
 
329
363
  #---------------------#
330
364
  # #attributes(*names) #
@@ -333,18 +367,16 @@ p Person.new(name: 'John').attributes # {"age"=>nil, "name"=>"John"}
333
367
  # Slices the attributes to include only the given keys.
334
368
  # Returns a hash containing the given keys (in their types).
335
369
 
336
- p person.attributes(:age) # {age: 20}
337
- p person.attributes(:age, :name) # {age: 20, name: "John Doe"}
338
- p person.attributes('age', 'name') # {"age"=>20, "name"=>"John Doe"}
370
+ person.attributes(:age) # {age: 20}
371
+ person.attributes(:age, :name) # {age: 20, name: 'John Doe'}
372
+ person.attributes('age', 'name') # {'age'=>20, 'name'=>'John Doe'}
339
373
  ```
340
374
 
341
375
  ## Built-in extensions
342
376
 
343
- You can use the method `Micro::Attributes.features()` or `Micro::Attributes.with()` to combine and require only the features that better fit your needs.
377
+ You can use the method `Micro::Attributes.with()` to combine and require only the features that better fit your needs.
344
378
 
345
- But, if you desire...
346
- 1. only one feature, use the `Micro::Attributes.feature()` method.
347
- 2. except one or more features, use the `Micro::Attributes.without()` method.
379
+ But, if you desire except one or more features, use the `Micro::Attributes.without()` method.
348
380
 
349
381
  ```ruby
350
382
  #===========================#
@@ -352,10 +384,10 @@ But, if you desire...
352
384
  #===========================#
353
385
 
354
386
  class Job
355
- include Micro::Attributes.feature(:diff)
387
+ include Micro::Attributes.with(:diff)
356
388
 
357
389
  attribute :id
358
- attribute :state, 'sleeping'
390
+ attribute :state, default: 'sleeping'
359
391
 
360
392
  def initialize(options)
361
393
  self.attributes = options
@@ -368,21 +400,20 @@ end
368
400
  #======================#
369
401
 
370
402
  class Job
371
- include Micro::Attributes.features
403
+ include Micro::Attributes.with_all_features
372
404
 
373
- attributes :id, state: 'sleeping'
405
+ attribute :id
406
+ attribute :state, default: 'sleeping'
374
407
  end
375
408
 
376
- # Note:
377
- # If `Micro::Attributes.features()` be invoked without arguments, a module with all features will be returned.
378
-
379
409
  #----------------------------------------------------------------------------#
380
410
  # Using the .with() method alias and adding the strict initialize extension. #
381
411
  #----------------------------------------------------------------------------#
382
412
  class Job
383
- include Micro::Attributes.with(:strict_initialize, :diff)
413
+ include Micro::Attributes.with(:diff, initialize: :strict)
384
414
 
385
- attributes :id, state: 'sleeping'
415
+ attribute :id
416
+ attribute :state, default: 'sleeping'
386
417
  end
387
418
 
388
419
  # Note:
@@ -392,28 +423,6 @@ end
392
423
  # include Micro::Attributes.with() # ArgumentError (Invalid feature name! Available options: diff, initialize, activemodel_validations)
393
424
  # end
394
425
 
395
- #===================================#
396
- # Alternatives to the methods above #
397
- #===================================#
398
-
399
- #---------------------------------------#
400
- # Via Micro::Attributes.to_initialize() #
401
- #---------------------------------------#
402
- class Job
403
- include Micro::Attributes.to_initialize(diff: true, activemodel_validations: true)
404
-
405
- # Same of `include Micro::Attributes.with(:initialize, :diff, :activemodel_validations)`
406
- end
407
-
408
- #----------------------------------------#
409
- # Via Micro::Attributes.to_initialize!() #
410
- #----------------------------------------#
411
- class Job
412
- include Micro::Attributes.to_initialize!(diff: false, activemodel_validations: true)
413
-
414
- # Same of `include Micro::Attributes.with(:strict_initialize, :activemodel_validations)`
415
- end
416
-
417
426
  #=====================================#
418
427
  # Loading except one or more features #
419
428
  # ----- #
@@ -422,7 +431,8 @@ end
422
431
  class Job
423
432
  include Micro::Attributes.without(:diff)
424
433
 
425
- attributes :id, state: 'sleeping'
434
+ attribute :id
435
+ attribute :state, default: 'sleeping'
426
436
  end
427
437
 
428
438
  # Note:
@@ -435,11 +445,11 @@ If your application uses ActiveModel as a dependency (like a regular Rails app).
435
445
 
436
446
  ```ruby
437
447
  class Job
438
- # include Micro::Attributes.with(:initialize, :activemodel_validations)
439
- # include Micro::Attributes.features(:initialize, :activemodel_validations)
440
- include Micro::Attributes.to_initialize(activemodel_validations: true)
448
+ include Micro::Attributes.with(:activemodel_validations)
449
+
450
+ attribute :id
451
+ attribute :state, default: 'sleeping'
441
452
 
442
- attributes :id, state: 'sleeping'
443
453
  validates! :id, :state, presence: true
444
454
  end
445
455
 
@@ -447,8 +457,27 @@ Job.new({}) # ActiveModel::StrictValidationFailed (Id can't be blank)
447
457
 
448
458
  job = Job.new(id: 1)
449
459
 
450
- p job.id # 1
451
- p job.state # "sleeping"
460
+ job.id # 1
461
+ job.state # 'sleeping'
462
+ ```
463
+
464
+ #### Attribute options
465
+
466
+ You can use the `validate` or `validates` options to define your attributes. e.g.
467
+
468
+ ```ruby
469
+ class Job
470
+ include Micro::Attributes.with(:activemodel_validations)
471
+
472
+ attribute :id, validates: { presence: true }
473
+ attribute :state, validate: :must_be_a_filled_string
474
+
475
+ def must_be_a_string
476
+ return if state.is_a?(String) && state.present?
477
+
478
+ errors.add(:state, 'must be a filled string')
479
+ end
480
+ end
452
481
  ```
453
482
 
454
483
  ### Diff extension
@@ -459,21 +488,20 @@ Provides a way to track changes in your object attributes.
459
488
  require 'securerandom'
460
489
 
461
490
  class Job
462
- # include Micro::Attributes.with(:initialize, :diff)
463
- # include Micro::Attributes.to_initialize(diff: true)
464
- include Micro::Attributes.features(:initialize, :diff)
491
+ include Micro::Attributes.with(:initialize, :diff)
465
492
 
466
- attributes :id, state: 'sleeping'
493
+ attribute :id
494
+ attribute :state, default: 'sleeping'
467
495
  end
468
496
 
469
497
  job = Job.new(id: SecureRandom.uuid())
470
498
 
471
- p job.id # A random UUID generated from SecureRandom.uuid(). e.g: "e68bcc74-b91c-45c2-a904-12f1298cc60e"
472
- p job.state # "sleeping"
499
+ job.id # A random UUID generated from SecureRandom.uuid(). e.g: 'e68bcc74-b91c-45c2-a904-12f1298cc60e'
500
+ job.state # 'sleeping'
473
501
 
474
502
  job_running = job.with_attribute(:state, 'running')
475
503
 
476
- p job_running.state # "running"
504
+ job_running.state # 'running'
477
505
 
478
506
  job_changes = job.diff_attributes(job_running)
479
507
 
@@ -481,50 +509,47 @@ job_changes = job.diff_attributes(job_running)
481
509
  # #present?, #blank?, #empty? #
482
510
  #-----------------------------#
483
511
 
484
- p job_changes.present? # true
485
- p job_changes.blank? # false
486
- p job_changes.empty? # false
512
+ job_changes.present? # true
513
+ job_changes.blank? # false
514
+ job_changes.empty? # false
487
515
 
488
516
  #-----------#
489
517
  # #changed? #
490
518
  #-----------#
491
- p job_changes.changed? # true
519
+ job_changes.changed? # true
492
520
 
493
- p job_changes.changed?(:id) # false
521
+ job_changes.changed?(:id) # false
494
522
 
495
- p job_changes.changed?(:state) # true
496
- p job_changes.changed?(:state, from: 'sleeping', to: 'running') # true
523
+ job_changes.changed?(:state) # true
524
+ job_changes.changed?(:state, from: 'sleeping', to: 'running') # true
497
525
 
498
526
  #----------------#
499
527
  # #differences() #
500
528
  #----------------#
501
- p job_changes.differences # {"state"=> {"from" => "sleeping", "to" => "running"}}
529
+ job_changes.differences # {'state'=> {'from' => 'sleeping', 'to' => 'running'}}
502
530
  ```
503
531
 
504
532
  ### Initialize extension
505
533
 
506
534
  1. Creates a constructor to assign the attributes.
507
- 2. Adds methods to build new instances when some data was assigned.
535
+ 2. Add methods to build new instances when some data was assigned.
508
536
 
509
537
  ```ruby
510
538
  class Job
511
- # include Micro::Attributes.with(:initialize)
512
- # include Micro::Attributes.feature(:initialize)
513
- # include Micro::Attributes.features(:initialize)
514
- include Micro::Attributes.to_initialize
539
+ include Micro::Attributes.with(:initialize)
515
540
 
516
541
  attributes :id, :state
517
542
  end
518
543
 
519
544
  job_null = Job.new({})
520
545
 
521
- p job.id # nil
522
- p job.state # nil
546
+ job.id # nil
547
+ job.state # nil
523
548
 
524
549
  job = Job.new(id: 1, state: 'sleeping')
525
550
 
526
- p job.id # 1
527
- p job.state # "sleeping"
551
+ job.id # 1
552
+ job.state # 'sleeping'
528
553
 
529
554
  ##############################################
530
555
  # Assigning new values to get a new instance #
@@ -536,9 +561,9 @@ p job.state # "sleeping"
536
561
 
537
562
  new_job = job.with_attribute(:state, 'running')
538
563
 
539
- puts new_job.id # 1
540
- puts new_job.state # running
541
- puts new_job.equal?(job) # false
564
+ new_job.id # 1
565
+ new_job.state # running
566
+ new_job.equal?(job) # false
542
567
 
543
568
  #--------------------#
544
569
  # #with_attributes() #
@@ -548,12 +573,12 @@ puts new_job.equal?(job) # false
548
573
 
549
574
  other_job = job.with_attributes(id: 2, state: 'killed')
550
575
 
551
- puts other_job.id # 2
552
- puts other_job.state # killed
553
- puts other_job.equal?(job) # false
576
+ other_job.id # 2
577
+ other_job.state # killed
578
+ other_job.equal?(job) # false
554
579
  ```
555
580
 
556
- ### Strict initialize extension
581
+ ### Strict initialize mode
557
582
 
558
583
  1. Creates a constructor to assign the attributes.
559
584
  2. Adds methods to build new instances when some data was assigned.
@@ -561,16 +586,13 @@ puts other_job.equal?(job) # false
561
586
 
562
587
  ```ruby
563
588
  class Job
564
- # include Micro::Attributes.with(:strict_initialize)
565
- # include Micro::Attributes.feature(:strict_initialize)
566
- # include Micro::Attributes.features(:strict_initialize)
567
- include Micro::Attributes.to_initialize!
589
+ include Micro::Attributes.with(initialize: :strict)
568
590
 
569
591
  attributes :id, :state
570
592
  end
571
- #----------------------------------------------------------------------------#
572
- # The strict_initialize extension will require all the keys when initialize. #
573
- #----------------------------------------------------------------------------#
593
+ #-----------------------------------------------------------------------#
594
+ # The strict initialize mode will require all the keys when initialize. #
595
+ #-----------------------------------------------------------------------#
574
596
 
575
597
  Job.new({})
576
598
 
@@ -583,20 +605,17 @@ Job.new({})
583
605
 
584
606
  job_null = Job.new(id: nil, state: nil)
585
607
 
586
- p job.id # nil
587
- p job.state # nil
608
+ job.id # nil
609
+ job.state # nil
588
610
 
589
611
  job = Job.new(id: 1, state: 'sleeping')
590
612
 
591
- p job.id # 1
592
- p job.state # "sleeping"
593
-
594
-
595
- # Note:
596
- # This extension works like the `initialize` extension.
597
- # So, look at its section to understand all the other features.
613
+ job.id # 1
614
+ job.state # 'sleeping'
598
615
  ```
599
616
 
617
+ > **Note**: This extension works like the `initialize` extension. So, look at its section to understand all of the other features.
618
+
600
619
  ## Development
601
620
 
602
621
  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.