deco_lite 0.3.0 → 0.3.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: 40f7b315deefbdf848f9d2743d27e672d3916da793f0bd32a705c7d34acac1f9
4
- data.tar.gz: b283948784b3fd9b1a4eaef20b7f0ca26a7de9b2971042c04a01021be6195d10
3
+ metadata.gz: 8a87d5a79f738b49d45b51c0128b4c252853c683363e7525df836fc7c46e4953
4
+ data.tar.gz: 1f07c897d0f88cd3609a8e6a880d0ce91b71210ee8952eb29148370b2f49f092
5
5
  SHA512:
6
- metadata.gz: 37a1083dfa95d51ab710fff1bab946edcc5b9fa825e37bf7f29c7a0174198d913469c8ac17f82b795949425f7e068236c73ca2ed9df50aba45bdfa3ef7cf1d18
7
- data.tar.gz: f3fbb8ab71dad6720dae8dc25179977757d55f7b802c2016ffc673fcdd423b3f86d04a406bd9a4bade6233efb5120cad1d7c2d7176045f44ec78da911311419a
6
+ metadata.gz: afc6320e0a1e9060dda231249fe16e62bf62d56f11ad7ffa9c4c6a0f094ef866173655c4ee57a419b3c4b83d0d7b7639230db22459f3c2d81d78cc6c4da2dde2
7
+ data.tar.gz: 6db8e3cb9a634669667eb288f4a4343106ad9be71630c1a9e95af366649b86e88459d0b79f1c71e09345a75805e643aa1e1e3a2836e2045bd1191bd78484685c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 0.3.1
2
+ * Changes
3
+ * Added `DecoLite::FieldRequireable::MISSING_REQUIRED_FIELD_ERROR_TYPE` for required field type errors.
4
+ * Update README.md with more examples.
5
+
1
6
  ### 0.3.0
2
7
  * Changes
3
8
  * `DecoLite::Model#new` how accepts a :hash named parameter that will load the Hash as if calling `DecoLite::Model.new.load!(hash: <hash>)`.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deco_lite (0.3.0)
4
+ deco_lite (0.3.1)
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)
data/README.md CHANGED
@@ -188,24 +188,117 @@ model.wife_info_address #=> 1 street, boonton, nj 07005
188
188
 
189
189
  #### Add validators to my model
190
190
 
191
- Simply add your `ActiveModel` validators just like you would any other `ActiveModel::Model` validator. However, be aware that (currently), any attribute (field) being validated that does not exist on the model, will raise a `NoMethodError` error:
191
+ 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.):
192
192
 
193
193
  ```ruby
194
194
  class Model < DecoLite::Model
195
195
  validates :first, :last, :address, presence: true
196
+ validates :age, numericality: true
196
197
  end
197
198
 
198
- model = Model.new(hash: { first: 'John', last: 'Doe' })
199
+ # No :address
200
+ model = Model.new(hash: { first: 'John', last: 'Doe', age: 25 })
201
+ model.respond_to? :address
202
+ #=> true
199
203
 
200
- # No :address; a NoMethodError error for :address will be raised.
201
- model.validate
202
- #=> undefined method 'address' for #<Model:0x00007f95931568c0 ... @field_names=[:first, :last], @first="John", @last="Doe", ...> (NoMethodError)
204
+ model.valid?
205
+ #=> false
206
+ model.errors.full_messages
207
+ #=> ["Address can't be blank"]
203
208
 
204
209
  model.load!(hash: { address: '123 park road, anytown, nj 01234' })
205
210
  model.validate
206
211
  #=> true
207
212
  ```
208
213
 
214
+ #### Validate whether or not certain fields were loaded
215
+
216
+ 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.
217
+
218
+ 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:
219
+ - Create a `DecoLite::Model` subclass.
220
+ - Override the `DecoLite::Model#required_fields` method to return the field names you want to validate.
221
+ - Use the `required_fields: nil` option when instantiating your model object.
222
+ - 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.
223
+
224
+ For example:
225
+
226
+ ```ruby
227
+ class Model < DecoLite::Model
228
+ # :age field is optional and it's value is optional.
229
+ validates :age, numericality: { only_integer: true }, allow_blank: true
230
+
231
+ def required_fields
232
+ # We want to ensure attr_accessors are created for these fields.
233
+ %i(first last address)
234
+ end
235
+ end
236
+
237
+ # Option "required_fields: :auto" is the default which will automatically create
238
+ # attr_accessors for fields returned from DecoLite::Model#required_fields, so we
239
+ # need to set this option to nil (i.e. required_fields: nil).
240
+ model = Model.new(options: { required_fields: nil })
241
+
242
+ model.validate
243
+ #=> false
244
+ model.errors.full_messages
245
+ #=> ["First field is missing", "Last field is missing", "Address field is missing"]
246
+
247
+ user = { first: 'John', last: 'Doe', address: '123 anystreet, anytown, nj 01234'}
248
+ model.load!(hash: user)
249
+ model.validate
250
+ #=> false
251
+ model.errors.full_messages
252
+ #=> ["Age is not a number"]
253
+ ```
254
+ #### Validate whether or not certain fields were loaded _and_ validate the data associated with these same fields
255
+
256
+ 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.
257
+
258
+ If you want to validate whether or not particular fields were loaded _and_ field data associated with these same fields, you'll have to use custom validation (e.g. override `DecoLite::FieldRequireable#validate_required_fields` and manually add your own validation and errors). This is because `DecoLite::Model#new` will automatically create `attr_accessors` for any attribute (field) that has an _explicit_ `ActiveModel` validation associated with it, and return false positives when you validate your model. In addition to this, you will need to do several other things outlined in the [Validate whether or not certain fields were loaded](#validate-whether-or-not-certain-fields-were-loaded) section.
259
+
260
+ For example:
261
+
262
+ ```ruby
263
+ class Model < DecoLite::Model
264
+ def required_fields
265
+ %i(first last address age)
266
+ end
267
+
268
+ def validate_required_fields
269
+ super
270
+
271
+ first = self.try(:first)
272
+ errors.add(:first, "can't be blank") if first.nil?
273
+
274
+ last = self.try(:last)
275
+ errors.add(:last, "can't be blank") if last.nil?
276
+
277
+ address = self.try(:address)
278
+ errors.add(:address, "can't be blank") if address.nil?
279
+
280
+ age = self.try(:age)
281
+ errors.add(:age, "can't be blank") if age.nil?
282
+ errors.add(:age, 'is not a number') unless /\d+/ =~ age
283
+ end
284
+ end
285
+ model = Model.new(options: { required_fields: nil })
286
+
287
+ model.validate
288
+ #=> false
289
+
290
+ model.errors.full_messages
291
+ #=> ["First field is missing",
292
+ "Last field is missing",
293
+ "Address field is missing",
294
+ "Age field is missing",
295
+ "First can't be blank",
296
+ "Last can't be blank",
297
+ "Address can't be blank",
298
+ "Age can't be blank",
299
+ "Age is not a number"]
300
+ ```
301
+
209
302
  #### Manually define attributes (fields) on my model
210
303
 
211
304
  Manually defining attributes on your subclass is possible, although there doesn't seem a valid reason to do so, since you can just use `DecoLite::Model#load!` to wire all this up for you automatically. However, if there _were_ a need to do this, you must add your `attr_reader` to the `DecoLite::Model@field_names` array, or an error will be raised _provided_ there are any conflicting field names being loaded using `DecoLite::Model#load!`. Note that the aforementioned error will be raised regardless of whether or not you set `options: { fields: :merge }`. This is because DecoLite considers any existing model attributes _not_ added to the model via `load!`to be native to the model object, and therefore will not allow you to create attr_accessors for existing model attributes because this can potentially be dangerous.
@@ -4,6 +4,8 @@ module DecoLite
4
4
  # Provides methods to manage fields that must be defined from
5
5
  # the dynamically loaded data.
6
6
  module FieldRequireable
7
+ MISSING_REQUIRED_FIELD_ERROR_TYPE = :missing_required_field
8
+
7
9
  # Returns field names that will be used to validate the presence of
8
10
  # dynamically created fields from loaded objects.
9
11
  #
@@ -23,7 +25,7 @@ module DecoLite
23
25
  required_fields.each do |field_name|
24
26
  next if required_field_exist? field_name: field_name
25
27
 
26
- errors.add(field_name, 'field is missing', type: :missing_required_field)
28
+ errors.add(field_name, 'field is missing', type: MISSING_REQUIRED_FIELD_ERROR_TYPE)
27
29
  end
28
30
  end
29
31
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the version of this gem.
4
4
  module DecoLite
5
- VERSION = '0.3.0'
5
+ VERSION = '0.3.1'
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.0
4
+ version: 0.3.1
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-26 00:00:00.000000000 Z
11
+ date: 2022-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel