deco_lite 0.2.5 → 0.3.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: 74286df21784817e45f4d615081bfeac44d90f13d8200bc8f066107e8d0f773f
4
- data.tar.gz: 57dcc52147494eb3caf59159cbb21bc23bb6788d0b6315ebc1ddd8cf1868c779
3
+ metadata.gz: 40f7b315deefbdf848f9d2743d27e672d3916da793f0bd32a705c7d34acac1f9
4
+ data.tar.gz: b283948784b3fd9b1a4eaef20b7f0ca26a7de9b2971042c04a01021be6195d10
5
5
  SHA512:
6
- metadata.gz: b79af6a65df899227821e4a02bf17587f1f423042a4280a54525c8469c1c3344f3dd2c3b16bd0de477c711d27ed04527295ca37e811c1c829037379509971ac6
7
- data.tar.gz: 7d1b5dea80d0af672713d18675166207e2d62ab51aff84045411d02344529a32de513df76d394e3769dfb14a69d0742f18e850398dc9b4cc6bac10eb5c72ecec
6
+ metadata.gz: 37a1083dfa95d51ab710fff1bab946edcc5b9fa825e37bf7f29c7a0174198d913469c8ac17f82b795949425f7e068236c73ca2ed9df50aba45bdfa3ef7cf1d18
7
+ data.tar.gz: f3fbb8ab71dad6720dae8dc25179977757d55f7b802c2016ffc673fcdd423b3f86d04a406bd9a4bade6233efb5120cad1d7c2d7176045f44ec78da911311419a
data/.reek.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  exclude_paths:
2
2
  - vendor
3
3
  - spec
4
+ - scratch.rb
4
5
  detectors:
5
6
  # TooManyInstanceVariables:
6
7
  # exclude:
data/.rubocop.yml CHANGED
@@ -116,7 +116,7 @@ Layout/LineLength:
116
116
  # Avoid methods longer than 15 lines of code.
117
117
  Metrics/MethodLength:
118
118
  Max: 20
119
- IgnoredMethods:
119
+ AllowedMethods:
120
120
  - swagger_path
121
121
  - operation
122
122
 
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ### 0.3.0
2
+ * Changes
3
+ * `DecoLite::Model#new` how accepts a :hash named parameter that will load the Hash as if calling `DecoLite::Model.new.load!(hash: <hash>)`.
4
+ * `DecoLite::Model#new now creates attr_accessors (fields) for any attribute that has an ActiveModel validator associated with it. This prevents errors raised when #validate is called before data is #load!ed.
5
+ * `DecoLite::Model#new` now creates attr_accessors (fields) for any field returned from `DecoLite::Model#reqired_fields` IF the required_fields: :auto option is set.
6
+ * bin/console now starts a pry-byebug session.
7
+
1
8
  ### 0.2.5
2
9
  * Changes
3
10
  * Remove init of `@field_names = []` in `Model#initialize` as unnecessary - FieldNamesPersistable takes care of this.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- deco_lite (0.2.5)
4
+ deco_lite (0.3.0)
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
@@ -15,17 +15,17 @@
15
15
 
16
16
  DecoLite is in development. I wouldn't expect breaking changes before v1.0.0; however, I can't completely rule this out. Currently, DecoLite only supports Hashes whose keys are `Symbols`, contain no embedded spaces, and conform to Ruby `attr_accessor` naming conventions. However, I'll certainly work out a solution for all this in future releases.
17
17
 
18
- TBD: Documentation regarding `DecoLite::Model` options, `DecoLite::Model#load` options: how these work, and how they play together (in the meantime, see the specs).
18
+ TBD: Documentation regarding `DecoLite::Model` options, `DecoLite::Model#load!` options: how these work, and how they play together (in the meantime, see the specs).
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 `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 `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.
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
 
26
26
  ```ruby
27
27
  # NOTE: keys :name and :age are not unique across this Hash.
28
- {
28
+ family = {
29
29
  name: 'John Doe',
30
30
  age: 35,
31
31
  wife: {
@@ -34,37 +34,66 @@ A `DecoLite::Model` will allow you to consume a Ruby Hash that you supply via th
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 (`DecoLite::Model#load`), and assign the values:
37
+ Given the above example, DecoLite will produce the following `attr_accessors` on the `DecoLite::Model` object when loaded (`DecoLite::Model#load!`), and assign the values:
38
38
 
39
39
  ```ruby
40
- name=, name #=> 'John Doe'
41
- age=, age #=> 35
42
- wife_name=, wife_name #=> 'Mary Doe'
43
- wife_age=, wife_age #=> 30
40
+ model = DecoLite::Model.new.load!(hash: family)
41
+
42
+ model.name #=> 'John Doe'
43
+ model.respond_to? :name= #=> true
44
+
45
+ model.age #=> 35
46
+ model.respond_to? :age= #=> true
47
+
48
+ model.wife_name #=> 'Mary Doe'
49
+ model.respond_to? :wife_name= #=> true
50
+
51
+ model.wife_age #=> 30
52
+ model.respond_to? :wife_age= #=> true
44
53
  ```
45
54
 
46
- `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:
55
+ `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:
47
56
 
48
57
  ```ruby
49
- {
58
+ grandpa = {
50
59
  name: 'Henry Doe',
51
60
  age: 85,
52
61
  }
62
+ # 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#load!.
53
63
  ```
54
64
 
55
- However, passing a `namespace: :grandpa` option to the `DecoLite::Model#load` method, would produce the following `attr_accessors`, ensuring uniquess:
65
+ However, passing a `namespace:` option (for example `namespace: :grandpa`) to the `DecoLite::Model#load!` method, would produce the following `attr_accessors`, ensuring their uniqueness:
66
+
56
67
  ```ruby
57
- # Unique now that the namespace "grandpa" has been applied.
58
- grandpa_name=, grandpa_name #=> 'Henry Doe'
59
- grandpa_age=, grandpa_age #=> 85
68
+ model.load!(hash: grandpa, options: { namespace: :grandpa })
69
+
70
+ # Unique now that the namespace: :grandpa has been applied:
71
+ model.grandpa_name #=> 'Henry Doe'
72
+ model.respond_to? :grandpa_name= #=> true
73
+
74
+ model.grandpa_age #=> 85
75
+ model.respond_to? :grandpa_age= #=> true
76
+
77
+ # All the other attributes on the model remain the same, and unique:
78
+ model.name #=> 'John Doe'
79
+ model.respond_to? :name= #=> true
80
+
81
+ model.age #=> 35
82
+ model.respond_to? :age= #=> true
83
+
84
+ model.wife_name #=> 'Mary Doe'
85
+ model.respond_to? :wife_name= #=> true
86
+
87
+ model.wife_age #=> 30
88
+ model.respond_to? :wife_age= #=> true
60
89
  ```
61
- ## Use Cases
90
+ ## Use cases
62
91
 
63
92
  ### General
64
- _Deco_ would _most likely_ thrive where the structure of the Hashe(s) consumed by the `DecoLite::Model#load` method is known. This is because of the way _Deco_ mangles loaded Hash key names to create unique `attr_accessor` names (see the Introduction section) although, I'm sure there are some metaprogramming geniuses out there that might prove me wrong. Assuming this is the case, _Deco_ would be ideal to handle Model attributes, Webservice JSON results (converted to Ruby Hash), JSON Web Token (JWT) payload, etc..
93
+ _Deco_ would _most likely_ thrive where the structure of the Hashe(s) consumed by the `DecoLite::Model#load!` method is known. This is because of the way _Deco_ mangles loaded Hash key names to create unique `attr_accessor` names (see the Introduction section); although, I'm sure there are some metaprogramming geniuses out there that might prove me wrong. Assuming this is the case, _Deco_ would be ideal to handle Model attributes, Webservice JSON results (converted to Ruby Hash), JSON Web Token (JWT) payload, etc..
65
94
 
66
95
  ### Rails
67
- Because `DecoLite::Model` includes `ActiveModel::Model`, it could also be ideal for use as a model in Rails applications, where a _decorator pattern_ can be used, and methods provided for use in Rails views; for example:
96
+ Because `DecoLite::Model` includes `ActiveModel::Model`, it could also be ideal for use as a model in Rails applications, where a _decorator pattern_ might be used, and decorator methods provided for use in Rails views; for example:
68
97
 
69
98
  ```ruby
70
99
  class ViewModel < DecoLite::Model
@@ -81,7 +110,7 @@ end
81
110
 
82
111
  view_model = ViewModel.new
83
112
 
84
- view_model.load(hash: { first: 'John', last: 'Doe' })
113
+ view_model.load!(hash: { first: 'John', last: 'Doe' })
85
114
 
86
115
  view_model.valid?
87
116
  #=> true
@@ -96,23 +125,7 @@ view_model.salutation
96
125
 
97
126
  Get creative. Please pop me an email and let me know how _you're_ using _Deco_.
98
127
 
99
- ## Installation
100
-
101
- Add this line to your application's Gemfile:
102
-
103
- ```ruby
104
- gem 'deco_lite'
105
- ```
106
-
107
- And then execute:
108
-
109
- $ bundle
110
-
111
- Or install it yourself as:
112
-
113
- $ gem install deco_lite
114
-
115
- ## Examples and Usage
128
+ ## Examples and usage
116
129
 
117
130
  ```ruby
118
131
  require 'deco_lite'
@@ -154,8 +167,8 @@ end
154
167
 
155
168
  couple = Couple.new
156
169
 
157
- couple.load(hash: husband, options: { namespace: :husband })
158
- couple.load(hash: wife, options: { namespace: :wife })
170
+ couple.load!(hash: husband, options: { namespace: :husband })
171
+ couple.load!(hash: wife, options: { namespace: :wife })
159
172
 
160
173
  # Will produce the following:
161
174
  model.live_together? #=> true
@@ -169,17 +182,35 @@ model.wife_name #=> Amy Doe
169
182
  model.wife_info_age #=> 20
170
183
  model.wife_info_address #=> 1 street, boonton, nj 07005
171
184
  ```
185
+ ## More examples and usage
186
+
187
+ ### I want to...
188
+
189
+ #### Add validators to my model
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:
192
+
193
+ ```ruby
194
+ class Model < DecoLite::Model
195
+ validates :first, :last, :address, presence: true
196
+ end
197
+
198
+ model = Model.new(hash: { first: 'John', last: 'Doe' })
199
+
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)
203
+
204
+ model.load!(hash: { address: '123 park road, anytown, nj 01234' })
205
+ model.validate
206
+ #=> true
207
+ ```
172
208
 
173
- ### Manually Defining Attributes
209
+ #### Manually define attributes (fields) on my model
174
210
 
175
- Manually defining attributes on your subclass is possible; however, you
176
- must add your attr_reader name to the `DecoLite::Model@field_names` array, or an error will be reaised _if_ there are any conflicting field names being loaded
177
- using `DecoLite::Model#load!`, regardless of setting the `{ fields: :merge }`
178
- option. This is because DecoLite assumes any existing attributes not added to
179
- the model via `load!`to be native to the object created, and therefore will not
180
- allow you to create attr_accessors for existing attributes, as this can potentially be dangerous.
211
+ 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.
181
212
 
182
- To avoid errors when manually defining attributes on the model that could potentially be in conflict with fields loaded using `DecoLite::Model#load!`, do the following:
213
+ To avoid errors when manually defining model attributes that could potentially conflict with fields loaded using `DecoLite::Model#load!`, do the following:
183
214
 
184
215
  ```ruby
185
216
  class JustBecauseYouCanDoesntMeanYouShould < DecoLite::Model
@@ -193,6 +224,35 @@ class JustBecauseYouCanDoesntMeanYouShould < DecoLite::Model
193
224
  end
194
225
  ```
195
226
 
227
+ However, the above is unnecessary as this can be easily accomplished using `DecoLite::Model#load!`:
228
+ ```ruby
229
+ model = Class.new(DecoLite::Model).new.load!(hash:{ existing_field: :existing_field_value })
230
+
231
+ model.field_names
232
+ #=> [:existing_field]
233
+
234
+ model.existing_field
235
+ #=> :existing_field_value
236
+
237
+ model.respond_to? :existing_field=
238
+ #=> true
239
+ ```
240
+ ## Installation
241
+
242
+ Add this line to your application's Gemfile:
243
+
244
+ ```ruby
245
+ gem 'deco_lite'
246
+ ```
247
+
248
+ And then execute:
249
+
250
+ $ bundle
251
+
252
+ Or install it yourself as:
253
+
254
+ $ gem install deco_lite
255
+
196
256
  ## Development
197
257
 
198
258
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/console CHANGED
@@ -10,6 +10,5 @@ require 'deco_lite'
10
10
  # (If you use this, don't forget to add pry to your Gemfile!)
11
11
  # require "pry"
12
12
  # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
13
+ require 'pry-byebug'
14
+ Pry.start
@@ -19,7 +19,8 @@ module DecoLite
19
19
  ":#{field_name} and/or :#{field_name}=; " \
20
20
  'this will raise an error when loading using strict mode ' \
21
21
  "(i.e. options: { #{OPTION_FIELDS}: :#{OPTION_FIELDS_STRICT} }) " \
22
- 'or if the method(s) are native to the object (e.g :to_s, :==, etc.).'
22
+ 'or if the method(s) are native to the object (e.g :to_s, :==, etc.). ' \
23
+ "Current options are: options: #{options.to_h}."
23
24
  end
24
25
 
25
26
  # This method returns true
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DecoLite
4
+ # Defines fields that may have attr_accessors automatically created for them
5
+ # on the model.
6
+ module FieldsAutoloadable
7
+ private
8
+
9
+ def auto_attr_accessors?
10
+ auto_attr_accessors.present?
11
+ end
12
+
13
+ # This method returns a Hash of fields that are implicitly defined either
14
+ # through ActiveModel validators or by returning them from the
15
+ # #required_fields Array.
16
+ def auto_attr_accessors
17
+ return @auto_attr_accessors.dup if defined?(@auto_attr_accessors)
18
+
19
+ @auto_attr_accessors = self.class.validators.map(&:attributes)
20
+ @auto_attr_accessors.concat(required_fields) if options.required_fields_auto?
21
+ @auto_attr_accessors = auto_attr_accessors_assign
22
+ end
23
+
24
+ def auto_attr_accessors_assign
25
+ @auto_attr_accessors.flatten.uniq.each_with_object({}) do |field_name, auto_attr_accessors_hash|
26
+ auto_attr_accessors_hash[field_name] = nil
27
+ end
28
+ end
29
+ end
30
+ end
@@ -16,8 +16,8 @@ module DecoLite
16
16
  return {} if hash.blank?
17
17
 
18
18
  load_service_options = merge_with_load_service_options deco_lite_options: deco_lite_options
19
- load_service.execute(hash: hash, options: load_service_options).tap do |h|
20
- h.each_pair do |field_name, value|
19
+ load_service.execute(hash: hash, options: load_service_options).tap do |service_hash|
20
+ service_hash.each_pair do |field_name, value|
21
21
  create_field_accessor field_name: field_name, options: deco_lite_options
22
22
  field_names << field_name unless field_names.include? field_name
23
23
  set_field_value(field_name: field_name, value: value, options: deco_lite_options)
@@ -4,7 +4,7 @@ module DecoLite
4
4
  # Provides methods to convert the object to a Hash.
5
5
  module Hashable
6
6
  def to_h
7
- field_names.each.each_with_object({}) do |field_name, hash|
7
+ field_names.each_with_object({}) do |field_name, hash|
8
8
  hash[field_name] = public_send field_name
9
9
  end
10
10
  end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
- require_relative 'field_creatable'
5
- require_relative 'field_requireable'
4
+ require_relative 'field_assignable'
6
5
  require_relative 'field_names_persistable'
6
+ require_relative 'field_requireable'
7
+ require_relative 'fields_auto_attr_accessable'
7
8
  require_relative 'hash_loadable'
8
9
  require_relative 'hashable'
9
10
  require_relative 'model_nameable'
@@ -14,9 +15,10 @@ module DecoLite
14
15
  # dynamic models that can be used as decorators.
15
16
  class Model
16
17
  include ActiveModel::Model
17
- include FieldCreatable
18
+ include FieldAssignable
18
19
  include FieldNamesPersistable
19
20
  include FieldRequireable
21
+ include FieldsAutoloadable
20
22
  include HashLoadable
21
23
  include Hashable
22
24
  include ModelNameable
@@ -24,13 +26,18 @@ module DecoLite
24
26
 
25
27
  validate :validate_required_fields
26
28
 
27
- def initialize(options: {})
29
+ def initialize(hash: {}, options: {})
28
30
  # Accept whatever options are sent, but make sure
29
31
  # we have defaults set up. #options_with_defaults
30
32
  # will merge options into OptionsDefaultable::DEFAULT_OPTIONS
31
33
  # so we have defaults for any options not passed in through
32
34
  # options.
33
35
  self.options = Options.with_defaults options
36
+
37
+ hash ||= {}
38
+
39
+ auto_fields = auto_attr_accessors.merge(hash)
40
+ load!(hash: auto_fields, options: options) if hash.present? || auto_attr_accessors?
34
41
  end
35
42
 
36
43
  def load!(hash:, options: {})
@@ -24,6 +24,10 @@ module DecoLite
24
24
  def namespace?
25
25
  namespace.present? || false
26
26
  end
27
+
28
+ def required_fields_auto?
29
+ required_fields == OPTION_REQUIRED_FIELDS_AUTO
30
+ end
27
31
  end
28
32
  validate_options! options: immutable_struct_ex.to_h
29
33
  immutable_struct_ex
@@ -2,16 +2,19 @@
2
2
 
3
3
  require_relative 'fields_optionable'
4
4
  require_relative 'namespace_optionable'
5
+ require_relative 'required_fields_optionable'
5
6
 
6
7
  module DecoLite
7
8
  # Defines default options and their optionn values.
8
9
  module OptionsDefaultable
9
10
  include DecoLite::FieldsOptionable
10
11
  include DecoLite::NamespaceOptionable
12
+ include DecoLite::RequiredFieldsOptionable
11
13
 
12
14
  DEFAULT_OPTIONS = {
13
15
  OPTION_FIELDS => OPTION_FIELDS_DEFAULT,
14
- OPTION_NAMESPACE => OPTION_NAMESPACE_DEFAULT
16
+ OPTION_NAMESPACE => OPTION_NAMESPACE_DEFAULT,
17
+ OPTION_REQUIRED_FIELDS => OPTION_REQUIRED_FIELDS_DEFAULT
15
18
  }.freeze
16
19
  end
17
20
  end
@@ -2,14 +2,16 @@
2
2
 
3
3
  require_relative 'fields_optionable'
4
4
  require_relative 'namespace_optionable'
5
+ require_relative 'required_fields_optionable'
5
6
 
6
7
  module DecoLite
7
8
  # Methods to validate options.
8
9
  module OptionsValidatable
9
10
  include DecoLite::FieldsOptionable
10
11
  include DecoLite::NamespaceOptionable
12
+ include DecoLite::RequiredFieldsOptionable
11
13
 
12
- OPTIONS = [OPTION_FIELDS, OPTION_NAMESPACE].freeze
14
+ OPTIONS = [OPTION_FIELDS, OPTION_NAMESPACE, OPTION_REQUIRED_FIELDS].freeze
13
15
 
14
16
  def validate_options!(options:)
15
17
  raise ArgumentError, 'options is not a Hash' unless options.is_a? Hash
@@ -17,8 +19,9 @@ module DecoLite
17
19
  validate_options_present! options: options
18
20
 
19
21
  validate_option_keys! options: options
20
- validate_option_fields! fields: options[:fields]
21
- validate_option_namespace! namespace: options[:namespace]
22
+ validate_option_fields! fields: options[OPTION_FIELDS]
23
+ validate_option_namespace! namespace: options[OPTION_NAMESPACE]
24
+ validate_option_required_fields! required_fields: options[OPTION_REQUIRED_FIELDS]
22
25
  end
23
26
 
24
27
  def validate_options_present!(options:)
@@ -45,5 +48,14 @@ module DecoLite
45
48
  raise ArgumentError, 'option :namespace value or type is invalid. A Symbol was expected, ' \
46
49
  "but '#{namespace}' (#{namespace.class}) was received."
47
50
  end
51
+
52
+ def validate_option_required_fields!(required_fields:)
53
+ # :required_fields is optional.
54
+ return if required_fields.blank? || OPTION_REQUIRED_FIELDS_VALUES.include?(required_fields)
55
+
56
+ raise ArgumentError,
57
+ "option :fields_required value or type is invalid. #{OPTION_REQUIRED_FIELDS_VALUES} (Symbol) " \
58
+ "was expected, but '#{required_fields}' (#{required_fields.class}) was received."
59
+ end
48
60
  end
49
61
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DecoLite
4
+ # Defines the fields option hash key and acceptable hash key values.
5
+ module RequiredFieldsOptionable
6
+ # The option hash key for this option.
7
+ OPTION_REQUIRED_FIELDS = :required_fields
8
+ # The valid option values for this option key.
9
+ OPTION_REQUIRED_FIELDS_AUTO = :auto
10
+ # The default value for this option.
11
+ OPTION_REQUIRED_FIELDS_DEFAULT = OPTION_REQUIRED_FIELDS_AUTO
12
+ # The valid option key values for this option.
13
+ OPTION_REQUIRED_FIELDS_VALUES = [OPTION_REQUIRED_FIELDS_AUTO].freeze
14
+ end
15
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the version of this gem.
4
4
  module DecoLite
5
- VERSION = '0.2.5'
5
+ VERSION = '0.3.0'
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.2.5
4
+ version: 0.3.0
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-22 00:00:00.000000000 Z
11
+ date: 2022-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -266,6 +266,7 @@ files:
266
266
  - lib/deco_lite/field_requireable.rb
267
267
  - lib/deco_lite/field_retrievable.rb
268
268
  - lib/deco_lite/field_validatable.rb
269
+ - lib/deco_lite/fields_auto_attr_accessable.rb
269
270
  - lib/deco_lite/fields_optionable.rb
270
271
  - lib/deco_lite/hash_loadable.rb
271
272
  - lib/deco_lite/hashable.rb
@@ -276,6 +277,7 @@ files:
276
277
  - lib/deco_lite/options.rb
277
278
  - lib/deco_lite/options_defaultable.rb
278
279
  - lib/deco_lite/options_validatable.rb
280
+ - lib/deco_lite/required_fields_optionable.rb
279
281
  - lib/deco_lite/version.rb
280
282
  homepage: https://github.com/gangelo/deco_lite
281
283
  licenses: