deco_lite 0.3.2 → 0.3.3

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: b5b5ed040bd367962dd57760a6a0e572b60485ba1d2d3630980ff1a090ca9075
4
- data.tar.gz: 76402762f17d93fd53495ddabf86487803b0014971db007f61f505727e933f56
3
+ metadata.gz: 77c440561731ca11332b76f0ee373e4568d4e84c11930d530d1dde9d5c097eb9
4
+ data.tar.gz: f771f70f192ae1c2b2d7a935933f7157cde64c6f44e9dc60d50e66d58e8abb05
5
5
  SHA512:
6
- metadata.gz: 584e1c07a160370bc9548e7a41dbaa9adcbee757a35a37925d02accf4ebe71d24cd9d2932e706724f5d8d64e8d98ff77f223224de27e5a0d817eb2675fea81ca
7
- data.tar.gz: 6a49a3ab8bdcb947341697577e130dd667c508095578536e8d003cfa1424f8e090f3c40e9ddc1376a3337cdcc9a26a02e836bc901c0ae36da39a8acaaae8cc46
6
+ metadata.gz: 6aa192d5c0d1c68860a4e41c31c3997307e90560d293ba6d2e1f5d30a82f537358988cfba766f34415c8321041f3844c2ac88d176a818647f13474f86171c3f6
7
+ data.tar.gz: e7910463ad7ede8f002af8bc0f46c220bcb715dce09d1690c10b3a3af7db66577acd372a607698470b2fd168a8295d3b24c1fd705601064f02e2f54e0f5ef350
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deco_lite (0.3.1)
4
+ deco_lite (0.3.3)
5
5
  activemodel (~> 7.0, >= 7.0.3.1)
6
6
  activesupport (~> 7.0, >= 7.0.3.1)
7
7
  immutable_struct_ex (~> 0.2.0)
@@ -25,7 +25,7 @@ GEM
25
25
  docile (1.4.0)
26
26
  i18n (1.12.0)
27
27
  concurrent-ruby (~> 1.0)
28
- immutable_struct_ex (0.2.2)
28
+ immutable_struct_ex (0.2.3)
29
29
  json (2.6.2)
30
30
  kwalify (0.7.2)
31
31
  mad_flatter (1.0.1.pre.beta)
@@ -63,7 +63,7 @@ GEM
63
63
  diff-lcs (>= 1.2.0, < 2.0)
64
64
  rspec-support (~> 3.11.0)
65
65
  rspec-support (3.11.0)
66
- rubocop (1.35.0)
66
+ rubocop (1.35.1)
67
67
  json (~> 2.3)
68
68
  parallel (~> 1.10)
69
69
  parser (>= 3.1.2.1)
data/README.md CHANGED
@@ -19,7 +19,7 @@ TBD: Documentation regarding `DecoLite::Model` options, `DecoLite::Model#load!`
19
19
 
20
20
  _Deco_ is a little gem that allows you to use the provided `DecoLite::Model` class (`include ActiveModel::Model`) to create Decorator classes which can be instantiated and used. Inherit from `DecoLite::Model` to create your own unique classes with custom functionality. A `DecoLite::Model` includes `ActiveModel::Model`, so validation can be applied using [ActiveModel validation helpers](https://api.rubyonrails.org/v6.1.3/classes/ActiveModel/Validations/HelperMethods.html) you are familiar with; or, you can roll your own - just like any other ActiveModel.
21
21
 
22
- A `DecoLite::Model` will allow you to consume a Ruby Hash that you supply via the initializer (`DecoLite::Model#new`) or via the `DecoLite::Model#load!` method. Your supplied Ruby Hashes are used to create `attr_accessor` attributes (_"fields"_) on the model. Each attribute created, is then assigned its value from the Hash loaded.
22
+ A `DecoLite::Model` will allow you to consume a Ruby Hash that you supply via the initializer (`DecoLite::Model#new`) or via the `DecoLite::Model#load!` method. Your supplied Ruby Hashes are used to create `attr_accessor` attributes (_"fields"_) on the model. Each attribute created, is then assigned its value from the Hash loaded. Any number of hashes can be consumed using the `DecoLite::Model#load!` method.
23
23
 
24
24
  `attr_accessor` names created are _mangled_ to include namespacing. This creates unique attribute names for nested Hashes that may include non-unique keys. For example:
25
25
 
@@ -34,7 +34,7 @@ family = {
34
34
  }
35
35
  }
36
36
  ```
37
- Given the above example, DecoLite will produce the following `attr_accessors` on the `DecoLite::Model` object when loaded, and assign the values:
37
+ Given the above example, DecoLite will produce the following `attr_accessors` on the `DecoLite::Model` object and assign the values:
38
38
 
39
39
  ```ruby
40
40
  # Or DecoLite::Model.new.load!(hash: family)
@@ -53,17 +53,21 @@ model.wife_age #=> 30
53
53
  model.respond_to? :wife_age= #=> true
54
54
  ```
55
55
 
56
- `DecoLite::Model#load!` can be called _multiple times_, on the same model, with different Hashes. This could potentially cause `attr_accessor` name clashes. In order to ensure unique `attr_accessor` names, a _"namespace"_ may be _explicitly_ provided to ensure uniqueness. For example, continuing from the previous example; if we were to call `DecoLite::Model#load!` a _second time_ with the following Hash, it would produce `attr_accessor` name clashes:
56
+ `DecoLite::Model#load!` can be called _multiple times_, on the same model, with different Hashes. This could potentially cause `attr_accessor` name clashes. In order to ensure unique `attr_accessor` names, a _"namespace"_ may be _explicitly_ provided to ensure uniqueness.
57
+
58
+ For example, **continuing from the previous example;** if we were to call `DecoLite::Model#load!` a _second time_ with the following Hash, this would potentially produce `attr_accessor` name clashes:
57
59
 
58
60
  ```ruby
59
61
  grandpa = {
60
62
  name: 'Henry Doe',
61
63
  age: 85,
62
64
  }
63
- # The :name and :age Hash keys above will produce :name/:name= and :age/:age= attr_accessors and clash because these were already added to the model when "John Doe" was loaded with the first call to DecoLite::Model.new(hash: family).
65
+ # The :name and :age Hash keys above will produce :name/:name= and :age/:age= attr_accessors
66
+ # and clash because these were already added to the model when "John Doe" was loaded with
67
+ # the first call to DecoLite::Model.new(hash: family).
64
68
  ```
65
69
 
66
- However, passing a `namespace:` option (for example `namespace: :grandpa`) to the `DecoLite::Model#load!` method, would produce the following `attr_accessors`, ensuring their uniqueness:
70
+ However, passing a `:namespace` option (for example `namespace: :grandpa`) to the `DecoLite::Model#load!` method, would produce the following `attr_accessors`, ensuring their uniqueness:
67
71
 
68
72
  ```ruby
69
73
  model.load!(hash: grandpa, options: { namespace: :grandpa })
@@ -88,6 +92,11 @@ model.respond_to? :wife_name= #=> true
88
92
  model.wife_age #=> 30
89
93
  model.respond_to? :wife_age= #=> true
90
94
  ```
95
+
96
+ ### For more examples and usage
97
+
98
+ For more examples and usage, see the [Examples and usage](#examples-and-usage) and [Mode examples and usage](#more-examples-and-usage) sections; there is also an "I want to..." section with examples you might encounter when using `DecoLite`.
99
+
91
100
  ## Use cases
92
101
 
93
102
  ### General
@@ -187,7 +196,7 @@ model.wife_info_address #=> 1 street, boonton, nj 07005
187
196
 
188
197
  #### Add validators to my model
189
198
 
190
- Simply add your `ActiveModel` validators just like you would any other `ActiveModel::Model` validator. However, be aware that (currently), any attribute (field) having an _explicit validation_ associated with it, will automatically cause an `attr_accessor` to be created for that field; this is to avoid `NoMethodErrors` when calling a validation method on the model (e.g. `#valid?`, `#validate`, etc.):
199
+ Simply add your `ActiveModel` validators just like you would any other `ActiveModel::Model` validator. However, be aware that (currently), any attribute (field) having an _explicit validation_ associated with it, will automatically cause an `attr_accessor` to be created for that field; this is to avoid `NoMethodErrors` when calling a validation method on the model (e.g. `#valid?`, `#validate`, etc.) *before* the data is loaded to create the associated `attr_accessors`:
191
200
 
192
201
  ```ruby
193
202
  class Model < DecoLite::Model
@@ -212,13 +221,13 @@ model.validate
212
221
 
213
222
  #### Validate whether or not certain fields were loaded
214
223
 
215
- To be clear, this has nothing to do with the _data_ associated with the fields loaded; rather, this has to do with whether or not the _fields themselves_ were created as attributes on your model as a result of loading data into your model. If you simply want to validate the _data_ loaded into your model, simply add `ActiveModel` validation, just like you would any other `ActiveModel` model, see the [Add validators to my model](#add-validators-to-my-model) section.
224
+ To be clear, this example does not validate the _data_ associated with the fields loaded; rather, this example validates whether or not the _fields themselves_ (`attr_accessors`) were created on your model as a result of loading data into your model. If you only want to validate the _data_ loaded into your model, simply add `ActiveModel` validation, just like you would any other `ActiveModel` model, see the [Add validators to my model](#add-validators-to-my-model) section.
216
225
 
217
- If you want to validate whether or not particular _fields_ were added to your model as attributes (i.e. `attr_accessor`), as a result of `#load!`ing data into your model, you need to do a few things:
226
+ If you want to validate whether or not particular _fields_ were added to your model as attributes (`attr_accessor`), as a result of `#load!`ing data into your model, you need to do a few things:
218
227
  - Create a `DecoLite::Model` subclass.
219
228
  - Override the `DecoLite::Model#required_fields` method to return the field names you want to validate.
220
229
  - Use the `required_fields: nil` option when instantiating your model object.
221
- - DO NOT add `ActiveModel` validators that _explicitly_ reference any field returned from `DecoLite::Model#required_fields`; this will cause `attr_accessors` to be created for these fields; consequently, `DecoLite::FieldRequireable#validate_required_fields` will _never_ return any errors because these fields will exist as attributes on your model. In other words, do not add `validates :first, :last, :address, presence: true` to your model if you need to validate whether or not the data you load into your model included fields :first, :last and :address.
230
+ - DO NOT add `ActiveModel` validators that _explicitly_ reference any field returned from `DecoLite::Model#required_fields`; this will cause `attr_accessors` to be created for these fields; consequently, `DecoLite::FieldRequireable#validate_required_fields` will *never* return any errors because these fields will exist as attributes on your model. In other words, do not add (for example) `validates :first, :last, :address, presence: true` to your model if you need to validate whether or not the data you load into your model includs fields `:first`, `:last` and `:address`.
222
231
 
223
232
  For example:
224
233
 
@@ -228,14 +237,15 @@ class Model < DecoLite::Model
228
237
  validates :age, numericality: { only_integer: true }, allow_blank: true
229
238
 
230
239
  def required_fields
231
- # We want to ensure attr_accessors are created for these fields.
240
+ # We want to ensure these fields were included as Hash keys during loading.
232
241
  %i(first last address)
233
242
  end
234
243
  end
244
+ ```
245
+
246
+ Option `required_fields: :auto` is the default which will automatically create `attr_accessors` for any field returned from the `DecoLite::Model#required_fields` method; therefore, we need to set the `:required_fields` option to `nil` (i.e. `required_fields: nil`). This will prohibit `DecoLite::Model` from automatically creating `attr_accessors` for `:first`, `:last` and `:address`, and achieve the results we want:
235
247
 
236
- # Option "required_fields: :auto" is the default which will automatically create
237
- # attr_accessors for fields returned from DecoLite::Model#required_fields, so we
238
- # need to set this option to nil (i.e. required_fields: nil).
248
+ ```ruby
239
249
  model = Model.new(options: { required_fields: nil })
240
250
 
241
251
  model.validate
@@ -243,7 +253,22 @@ model.validate
243
253
  model.errors.full_messages
244
254
  #=> ["First field is missing", "Last field is missing", "Address field is missing"]
245
255
 
246
- user = { first: 'John', last: 'Doe', address: '123 anystreet, anytown, nj 01234'}
256
+ # If we load data that includes :first, :last, and :address Hash keys even with
257
+ # nil data, our ":<field> field is missing" errors go away; in this scenario,
258
+ # we're validating the presence of the FIELDS, not the data associated with
259
+ # these fields!
260
+ model.load!(hash: { first: nil, last: nil, address: nil })
261
+ model.validate
262
+ #=> true
263
+ model.errors.full_messages
264
+ #=> []
265
+
266
+ user = {
267
+ first: 'John',
268
+ last: 'Doe',
269
+ address: '123 anystreet, anytown, nj 01234',
270
+ age: 'x'
271
+ }
247
272
  model.load!(hash: user)
248
273
  model.validate
249
274
  #=> false
@@ -316,19 +341,21 @@ class JustBecauseYouCanDoesntMeanYouShould < DecoLite::Model
316
341
  end
317
342
  ```
318
343
 
319
- However, the above is unnecessary as this can be easily accomplished using `DecoLite::Model#load!`:
344
+ However, the above is unnecessary as this can be easily accomplished by passing a `Hash` to the initializer or by using `DecoLite::Model#load!`:
345
+
320
346
  ```ruby
321
- model = Class.new(DecoLite::Model).new.load!(hash:{ existing_field: :existing_field_value })
347
+ model = Class.new(DecoLite::Model).new(hash:{ existing_field: :value })
322
348
 
323
349
  model.field_names
324
350
  #=> [:existing_field]
325
351
 
326
352
  model.existing_field
327
- #=> :existing_field_value
353
+ #=> :value
328
354
 
329
355
  model.respond_to? :existing_field=
330
356
  #=> true
331
357
  ```
358
+
332
359
  ## Installation
333
360
 
334
361
  Add this line to your application's Gemfile:
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the version of this gem.
4
4
  module DecoLite
5
- VERSION = '0.3.2'
5
+ VERSION = '0.3.3'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deco_lite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gene M. Angelo, Jr.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-29 00:00:00.000000000 Z
11
+ date: 2022-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel