serega 0.39.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a223242ae8bce14755fa2cbb444ff78728d95fccb0ce3077c212706e39e4ddcc
4
- data.tar.gz: b8e1d3bdf11a57091cfd22eb31bb017979382df4b2166b05f746d064dc486f6e
3
+ metadata.gz: 42da0ff66dc5eeb282fbb72144f78bcfc8ded1aa8609122ded10093f6c83dd96
4
+ data.tar.gz: f9fb2a2628756540cd08a5449a21883b0cf28ec45db8f461ee0944fd0f3812e9
5
5
  SHA512:
6
- metadata.gz: d815a4a17625533c34659451851c33806bd4d1e0bf862945b2118d52315726184322c55d989378cf8ac7f9b4d04a392dfa344af196491b984ddc1d094d15c063
7
- data.tar.gz: ecf2be1cff661bfe8e99103748276969f72442b04b8308dd136d137dc88f28dfb543ad73a5e0880a31eb6f6c4a6a51e6ccab307a92f867551ff4b19b56d38f73
6
+ metadata.gz: 1355573b7cb8d30ffbf844be46c03c4a5233fa9c190fa5e03fd39c0d1a396b9f7a19e7e2d4cf3afbd0445cd1d8dfc8ebbd1df6d77d91d338c0ede561c836fb99
7
+ data.tar.gz: 90ccd454b970598f9921ec1a6c9feab325a373d5628f884515141d34a3a72e7012273e37aa903046e064876f92bd956783ef3a9b93732ee23a8bcc8bec154ee3
data/README.md CHANGED
@@ -26,6 +26,7 @@ It has some great features:
26
26
  keeping the code dry
27
27
  - Conditional attributes - ([if][if] plugin)
28
28
  - Auto camelCase keys - [camel_case][camel_case] plugin
29
+ - Serializing Hash records - [hash_access][hash_access] attribute option
29
30
 
30
31
  ## Installation
31
32
 
@@ -74,8 +75,9 @@ class UserSerializer < Serega
74
75
  # Regular attribute
75
76
  attribute :first_name
76
77
 
77
- # Option :method specifies the method that must be called on the
78
- # serialized object
78
+ # Option :method specifies the name used to read the attribute's value —
79
+ # a method called on the serialized object by default, or a Hash key when
80
+ # combined with :hash_access
79
81
  attribute :first_name, method: :old_first_name
80
82
 
81
83
  # Attribute blocks below require a base serializer for nested serializers.
@@ -494,6 +496,12 @@ class AppSerializer < Serega
494
496
  # proc { |object, batches:| batches[:counter][object.id] }
495
497
  config.batch_id_option = :id
496
498
 
499
+ # Defaults for the `hash_access:` attribute option — `default_mode` is
500
+ # what `hash_access: true` (and a Hash form omitting :mode) resolves to.
501
+ # See "Serializing Hash records".
502
+ config.hash_access.default_mode = :symbol # the default
503
+ config.hash_access.default_allow_missing_key = false # the default
504
+
497
505
  # Parent class for nested serializers defined with attribute blocks.
498
506
  # Usually a settings-only serializer, e.g. `config.base_serializer = self`
499
507
  # in an application base serializer class. There is no default — an
@@ -664,6 +672,69 @@ end
664
672
 
665
673
  ---
666
674
 
675
+ ## Serializing Hash records
676
+
677
+ (objects should implement `#[]`, `#fetch`, and `#key?` - Hash already has them)
678
+
679
+ The `hash_access: <mode>` attribute option makes an attribute read its value from
680
+ Hash keys instead of calling a method.
681
+
682
+ Allowed `<mode>`:
683
+
684
+ - `:symbol` reads record[:name]
685
+ - `:string` reads record["name"]
686
+ - `true` shorthand for `config.hash_access.default_mode` (`:symbol` by default)
687
+
688
+ By default missing keys will raise `KeyError`.
689
+
690
+ `config.hash_access.default_allow_missing_key = true` will change `KeyError`
691
+ to return `nil` value instead. `config.hash_access.default_mode = <mode>`
692
+ changes what `true` (and a Hash form omitting `:mode`) resolves to.
693
+
694
+ ```ruby
695
+ class UserSerializer < Serega
696
+ config.hash_access.default_mode = :symbol # the default
697
+ config.hash_access.default_allow_missing_key = true # false by default
698
+
699
+ attribute :name, hash_access: true # reads record[:name] (config.hash_access.default_mode)
700
+ attribute :name, hash_access: :symbol # reads record[:name]
701
+ attribute :name, hash_access: :string # reads record["name"]
702
+
703
+ # Use long form if you need to override `allow_missing_key`
704
+ attribute :name, hash_access: { allow_missing_key: false }
705
+ attribute :name, hash_access: { mode: :symbol, allow_missing_key: false }
706
+ attribute :name, hash_access: { mode: :string, allow_missing_key: false }
707
+ end
708
+ ```
709
+
710
+ Delegated attributes configure hash access **per step**:
711
+
712
+ - `to_hash_access` configures reading `<mode>` for intermediate object
713
+ - `hash_access` configures reading `<mode>` for final key
714
+
715
+ ```ruby
716
+ # reads `record.address.city` (no hash access)
717
+ attribute :city, delegate: { to: :address } # record.address.city
718
+
719
+ # reads record.address[:city]
720
+ attribute :city, delegate: { to: :address, hash_access: :symbol }
721
+
722
+ # reads record[:address].city
723
+ attribute :city, delegate: { to: :address, to_hash_access: :symbol }
724
+
725
+ # reads record[:address][:city]
726
+ attribute :city, delegate: { to: :address, to_hash_access: :symbol, hash_access: :symbol }
727
+
728
+ # reads record["address"] and if exists returns record["address"][:city]
729
+ attribute :city,
730
+ delegate: {
731
+ to: :address,
732
+ allow_nil: true,
733
+ to_hash_access: { mode: :string, allow_missing_key: true },
734
+ hash_access: { mode: :symbol, allow_missing_key: false }
735
+ }
736
+ ```
737
+
667
738
  ## Plugins
668
739
 
669
740
  ### Plugin :activerecord_preloads
@@ -1128,6 +1199,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
1128
1199
  [context_metadata]: #plugin-context_metadata
1129
1200
  [depth_limit]: #plugin-depth_limit
1130
1201
  [formatters]: #plugin-formatters
1202
+ [hash_access]: #serializing-hash-records
1131
1203
  [metadata]: #plugin-metadata
1132
1204
  [preloads]: #preloads
1133
1205
  [presenter]: #plugin-presenter
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.39.0
1
+ 0.40.0
@@ -254,7 +254,10 @@ class Serega
254
254
  end
255
255
 
256
256
  def prepare_keyword_block
257
- AttributeValueResolvers::KeywordResolver.get(method_name)
257
+ mode, allow_nil = hash_access
258
+ return AttributeValueResolvers::KeywordResolver.get(method_name) unless mode
259
+
260
+ AttributeValueResolvers::HashAccessResolver.get(method_name, mode, allow_nil)
258
261
  end
259
262
 
260
263
  def prepare_batch_loader_block
@@ -291,15 +294,68 @@ class Serega
291
294
  init_opts.fetch(:default) { many ? FROZEN_EMPTY_ARRAY : nil }
292
295
  end
293
296
 
297
+ # `delegate: {to_hash_access: ...}` configures hash access for the
298
+ # intermediate (:to) read, `delegate: {hash_access: ...}` for the
299
+ # final (:method) read. A step without its sub-option keeps a plain
300
+ # method read.
294
301
  def prepare_delegate_block
295
302
  delegate = init_opts[:delegate]
296
303
  return unless delegate
297
304
 
298
305
  key_method_name = delegate[:method] || method_name
299
306
  delegate_to = delegate[:to]
307
+ delegate_allow_nil = delegate.fetch(:allow_nil) { config.delegate_default_allow_nil }
308
+
309
+ to_access = delegate[:to_hash_access]
310
+ final_access = delegate[:hash_access]
311
+ unless to_access || final_access
312
+ return AttributeValueResolvers::DelegateResolver.get(delegate_to, key_method_name, delegate_allow_nil)
313
+ end
314
+
315
+ to_step = delegate_to_step(delegate_to, to_access)
316
+ final_step = delegate_final_step(key_method_name, final_access)
317
+ AttributeValueResolvers::HashAccessDelegateResolver.get(to_step, final_step, delegate_allow_nil)
318
+ end
319
+
320
+ def delegate_to_step(delegate_to, access)
321
+ return AttributeValueResolvers::Keyword.new(delegate_to) unless access
322
+
323
+ mode, allow_missing_key = parse_hash_access(access)
324
+ AttributeValueResolvers::HashAccessKeyword.new(delegate_to, mode, allow_missing_key)
325
+ end
326
+
327
+ def delegate_final_step(key_method_name, access)
328
+ return AttributeValueResolvers::Keyword.new(key_method_name) unless access
300
329
 
301
- allow_nil = delegate.fetch(:allow_nil) { config.delegate_default_allow_nil }
302
- AttributeValueResolvers::DelegateResolver.get(delegate_to, key_method_name, allow_nil)
330
+ mode, allow_missing_key = parse_hash_access(access)
331
+ AttributeValueResolvers::HashAccessKeyword.new(key_method_name, mode, allow_missing_key)
332
+ end
333
+
334
+ # Resolves the :hash_access option of plain attributes
335
+ # @return [Array(Symbol, Boolean), nil] mode and allow_missing_key pair,
336
+ # or nil when hash access is not enabled for this attribute
337
+ def hash_access
338
+ option = init_opts[:hash_access]
339
+ return unless option
340
+
341
+ parse_hash_access(option)
342
+ end
343
+
344
+ # Resolves a :hash_access value (`true`, a Symbol mode or a
345
+ # `{mode:, allow_missing_key:}` Hash) into a mode and allow_missing_key
346
+ # pair. `true` and a Hash omitting :mode resolve to
347
+ # `config.hash_access.default_mode`.
348
+ def parse_hash_access(option)
349
+ defaults = config.hash_access
350
+
351
+ case option
352
+ when true then [defaults.default_mode, defaults.default_allow_missing_key]
353
+ when Symbol then [option, defaults.default_allow_missing_key]
354
+ else
355
+ mode = option.fetch(:mode) { defaults.default_mode }
356
+ allow_missing_key = option.fetch(:allow_missing_key) { defaults.default_allow_missing_key }
357
+ [mode, allow_missing_key]
358
+ end
303
359
  end
304
360
 
305
361
  # Prepares preloads for this attribute.
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module AttributeValueResolvers
5
+ #
6
+ # Builds value resolver for attributes with the :hash_access option
7
+ #
8
+ class HashAccessResolver
9
+ # Allowed hash access modes
10
+ MODES = %i[symbol string].freeze
11
+
12
+ #
13
+ # Creates resolver that reads a key from Hash records
14
+ #
15
+ # @param name [Symbol, String] hash key
16
+ # @param mode [Symbol] hash access mode (:symbol, :string)
17
+ # @param allow_missing_key [Boolean] whether a missing key is read via `record[key]` rather than raising
18
+ #
19
+ # @return [HashAccessKeyword] resolver instance
20
+ #
21
+ def self.get(name, mode, allow_missing_key)
22
+ HashAccessKeyword.new(name, mode, allow_missing_key)
23
+ end
24
+ end
25
+
26
+ #
27
+ # Builds value resolver for attributes with the :delegate option using
28
+ # hash access on any of its steps
29
+ #
30
+ class HashAccessDelegateResolver
31
+ #
32
+ # Creates resolver that delegates through the provided step readers
33
+ #
34
+ # @param to_step [#call] reader of the intermediate object
35
+ # @param final_step [#call] reader of the final value
36
+ # @param delegate_allow_nil [Boolean] whether a nil intermediate object resolves to nil
37
+ #
38
+ # @return [HashAccessDelegate, HashAccessDelegateAllowNil] resolver instance
39
+ #
40
+ def self.get(to_step, final_step, delegate_allow_nil)
41
+ delegate_allow_nil ? HashAccessDelegateAllowNil.new(to_step, final_step) : HashAccessDelegate.new(to_step, final_step)
42
+ end
43
+ end
44
+
45
+ #
46
+ # Value resolver for attributes with the :hash_access option
47
+ #
48
+ class HashAccessKeyword
49
+ def initialize(name, mode, allow_missing_key)
50
+ @key = (mode == :symbol) ? name.to_sym : name.to_s
51
+ @allow_missing_key = allow_missing_key
52
+ end
53
+
54
+ #
55
+ # Reads the key from the record
56
+ #
57
+ # @param object [Object] serialized object or delegation step value
58
+ # @return [Object] the value found
59
+ #
60
+ def call(object)
61
+ return object[@key] if @allow_missing_key
62
+
63
+ object.fetch(@key) do
64
+ default = object[@key]
65
+ next default unless default.nil?
66
+
67
+ raise KeyError.new("key not found: #{@key.inspect}", key: @key, receiver: object)
68
+ end
69
+ end
70
+ end
71
+
72
+ #
73
+ # Value resolver for attributes with :hash_access and :delegate (without :allow_nil) options
74
+ #
75
+ class HashAccessDelegate
76
+ def initialize(to_step, final_step)
77
+ @to_step = to_step
78
+ @final_step = final_step
79
+ end
80
+
81
+ #
82
+ # Delegates the value reading through the intermediate object
83
+ #
84
+ # @param object [Object] serialized object
85
+ # @return [Object] the value found
86
+ #
87
+ def call(object)
88
+ @final_step.call(@to_step.call(object))
89
+ end
90
+ end
91
+
92
+ #
93
+ # Value resolver for attributes with :hash_access and :delegate (with :allow_nil) options
94
+ #
95
+ class HashAccessDelegateAllowNil
96
+ def initialize(to_step, final_step)
97
+ @to_step = to_step
98
+ @final_step = final_step
99
+ end
100
+
101
+ #
102
+ # Delegates the value reading through the intermediate object,
103
+ # resolving a nil intermediate to nil
104
+ #
105
+ # @param object [Object] serialized object
106
+ # @return [Object, nil] the value found
107
+ #
108
+ def call(object)
109
+ intermediate = @to_step.call(object)
110
+ return if intermediate.nil?
111
+
112
+ @final_step.call(intermediate)
113
+ end
114
+ end
115
+ end
116
+ end
data/lib/serega/config.rb CHANGED
@@ -25,6 +25,7 @@ class Serega
25
25
  preload
26
26
  batch
27
27
  base_serializer
28
+ hash_access
28
29
  ].freeze,
29
30
  serialize_keys: %i[context many].freeze,
30
31
  check_attribute_name: true,
@@ -35,7 +36,8 @@ class Serega
35
36
  auto_preload_excluded_methods: %i[itself].freeze,
36
37
  hide_by_default: false,
37
38
  batch_id_option: :id,
38
- base_serializer: nil
39
+ base_serializer: nil,
40
+ hash_access: {default_mode: :symbol, default_allow_missing_key: false}
39
41
  }.freeze
40
42
  # :nocov:
41
43
 
@@ -205,6 +207,12 @@ class Serega
205
207
  end
206
208
  end
207
209
 
210
+ # Returns the hash_access config object
211
+ # @return [Serega::SeregaConfig::HashAccessConfig] hash_access config object
212
+ def hash_access
213
+ @hash_access ||= HashAccessConfig.new(opts.fetch(:hash_access))
214
+ end
215
+
208
216
  # Returns :max_cached_plans_per_serializer_count config option
209
217
  # @return [Boolean] Current :max_cached_plans_per_serializer_count config option
210
218
  def max_cached_plans_per_serializer_count
@@ -252,6 +260,57 @@ class Serega
252
260
  end
253
261
  end
254
262
 
263
+ #
264
+ # Config for the `hash_access:` attribute option
265
+ #
266
+ class HashAccessConfig
267
+ # @return [Hash] hash_access config options
268
+ attr_reader :opts
269
+
270
+ #
271
+ # Initializes HashAccessConfig object
272
+ #
273
+ # @param opts [Hash] hash_access config options
274
+ #
275
+ # @return [Serega::SeregaConfig::HashAccessConfig]
276
+ #
277
+ def initialize(opts)
278
+ @opts = opts
279
+ end
280
+
281
+ # @return [Symbol] mode used by `hash_access: true` (default :symbol)
282
+ def default_mode
283
+ opts.fetch(:default_mode)
284
+ end
285
+
286
+ # Sets the mode used by `hash_access: true`
287
+ # @param value [Symbol] one of :symbol, :string
288
+ # @return [Symbol] new default mode
289
+ def default_mode=(value)
290
+ unless AttributeValueResolvers::HashAccessResolver::MODES.include?(value)
291
+ raise SeregaError, "Invalid hash_access default_mode #{value.inspect}. Allowed modes: :symbol, :string"
292
+ end
293
+
294
+ opts[:default_mode] = value
295
+ end
296
+
297
+ # @return [Boolean] allow_missing_key used when an attribute omits it
298
+ def default_allow_missing_key
299
+ opts.fetch(:default_allow_missing_key)
300
+ end
301
+
302
+ # Sets the allow_missing_key used when an attribute omits it
303
+ # @param value [Boolean]
304
+ # @return [Boolean] new default allow_missing_key
305
+ def default_allow_missing_key=(value)
306
+ unless value == true || value == false
307
+ raise SeregaError, "Invalid hash_access default_allow_missing_key #{value.inspect}. Must be a Boolean"
308
+ end
309
+
310
+ opts[:default_allow_missing_key] = value
311
+ end
312
+ end
313
+
255
314
  include SeregaConfigInstanceMethods
256
315
  extend Serega::SeregaHelpers::SerializerClassHelper
257
316
  end
@@ -132,11 +132,15 @@ class Serega
132
132
  superclass.modified?
133
133
  end
134
134
 
135
+ # Marks the class as modified, then includes the module
136
+ # @return [void]
135
137
  def include(*modules)
136
138
  @modified = true
137
139
  super
138
140
  end
139
141
 
142
+ # Marks the class as modified, then prepends the module
143
+ # @return [void]
140
144
  def prepend(*modules)
141
145
  @modified = true
142
146
  super
@@ -34,6 +34,8 @@ class Serega
34
34
  check_opt_delegate_to(delegate_opts)
35
35
  check_opt_delegate_method(delegate_opts)
36
36
  check_opt_delegate_allow_nil(delegate_opts)
37
+ check_opt_delegate_to_hash_access(delegate_opts)
38
+ check_opt_delegate_hash_access(delegate_opts)
37
39
  check_opt_delegate_extra_opts(delegate_opts)
38
40
  end
39
41
 
@@ -48,12 +50,51 @@ class Serega
48
50
  Utils::CheckOptIsStringOrSymbol.call(delegate_opts, :method)
49
51
  end
50
52
 
53
+ # Covers only the intermediate object being nil — a missing key on
54
+ # either step is each step's own :allow_missing_key sub-option.
51
55
  def check_opt_delegate_allow_nil(delegate_opts)
52
56
  Utils::CheckOptIsBool.call(delegate_opts, :allow_nil)
53
57
  end
54
58
 
59
+ # Hash access of the intermediate (:to) step. Accepts the same
60
+ # forms as the final (:method) step.
61
+ def check_opt_delegate_to_hash_access(delegate_opts)
62
+ check_hash_access_value(delegate_opts, :to_hash_access)
63
+ end
64
+
65
+ # Hash access of the final (:method) step. Accepts the same forms
66
+ # as the attribute :hash_access option.
67
+ def check_opt_delegate_hash_access(delegate_opts)
68
+ check_hash_access_value(delegate_opts, :hash_access)
69
+ end
70
+
71
+ def check_hash_access_value(delegate_opts, opt_name)
72
+ return unless delegate_opts.key?(opt_name)
73
+
74
+ value = delegate_opts[opt_name]
75
+ case value
76
+ when true, false then nil
77
+ when Symbol then check_hash_access_mode(value)
78
+ when Hash
79
+ Utils::CheckAllowedKeys.call(value, %i[mode allow_missing_key], opt_name)
80
+ check_hash_access_mode(value[:mode]) if value.key?(:mode)
81
+ Utils::CheckOptIsBool.call(value, :allow_missing_key)
82
+ else
83
+ raise SeregaError,
84
+ "Invalid delegate option :#{opt_name} => #{value.inspect}." \
85
+ " It must be a Boolean, a Symbol mode (:symbol, :string)" \
86
+ " or a Hash with :mode and :allow_missing_key keys"
87
+ end
88
+ end
89
+
90
+ def check_hash_access_mode(mode)
91
+ return true if AttributeValueResolvers::HashAccessResolver::MODES.include?(mode)
92
+
93
+ raise SeregaError, "Invalid :hash_access mode #{mode.inspect}. Allowed modes: :symbol, :string"
94
+ end
95
+
55
96
  def check_opt_delegate_extra_opts(delegate_opts)
56
- Utils::CheckAllowedKeys.call(delegate_opts, %i[to method allow_nil], :delegate)
97
+ Utils::CheckAllowedKeys.call(delegate_opts, %i[to method allow_nil to_hash_access hash_access], :delegate)
57
98
  end
58
99
 
59
100
  def check_usage_with_other_params(opts)
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaValidations
5
+ module Attribute
6
+ #
7
+ # Attribute `:hash_access` option validator
8
+ #
9
+ class CheckOptHashAccess
10
+ class << self
11
+ #
12
+ # Checks attribute :hash_access option
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:hash_access)
22
+
23
+ value = opts[:hash_access]
24
+ check_value(value)
25
+ check_usage_with_other_params(opts) if value
26
+ end
27
+
28
+ private
29
+
30
+ def check_value(value)
31
+ case value
32
+ when true, false then nil
33
+ when Symbol then check_mode(value)
34
+ when Hash
35
+ Utils::CheckAllowedKeys.call(value, %i[mode allow_missing_key], :hash_access)
36
+ check_mode(value[:mode]) if value.key?(:mode)
37
+ check_allow_missing_key(value[:allow_missing_key]) if value.key?(:allow_missing_key)
38
+ else
39
+ raise SeregaError,
40
+ "Invalid option :hash_access => #{value.inspect}." \
41
+ " It must be a Boolean, a Symbol mode (:symbol, :string)" \
42
+ " or a Hash with :mode and :allow_missing_key keys"
43
+ end
44
+ end
45
+
46
+ def check_mode(mode)
47
+ return if AttributeValueResolvers::HashAccessResolver::MODES.include?(mode)
48
+
49
+ raise SeregaError, "Invalid :hash_access mode #{mode.inspect}. Allowed modes: :symbol, :string"
50
+ end
51
+
52
+ def check_allow_missing_key(allow_missing_key)
53
+ return if allow_missing_key == true || allow_missing_key == false
54
+
55
+ raise SeregaError, "Invalid :hash_access option :allow_missing_key => #{allow_missing_key.inspect}. Must be a Boolean"
56
+ end
57
+
58
+ # The :const, :value and :batch options do not read the serialized
59
+ # object by attribute name, so hash access can not affect them.
60
+ # Delegated attributes configure hash access per step with the
61
+ # `delegate: {to_hash_access:, hash_access:}` sub-options.
62
+ def check_usage_with_other_params(opts)
63
+ raise SeregaError, "Option :hash_access can not be used together with option :const" if opts.key?(:const)
64
+ raise SeregaError, "Option :hash_access can not be used together with option :value" if opts.key?(:value)
65
+ raise SeregaError, "Option :hash_access can not be used together with option :batch" if opts.key?(:batch)
66
+
67
+ if opts.key?(:delegate)
68
+ raise SeregaError,
69
+ "Option :hash_access can not be used together with option :delegate." \
70
+ " Use the delegate :to_hash_access (intermediate step) and" \
71
+ " :hash_access (final step) sub-options instead"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -62,6 +62,7 @@ class Serega
62
62
  Attribute::CheckOptBaseSerializer.call(opts, block)
63
63
  Attribute::CheckOptConst.call(opts)
64
64
  Attribute::CheckOptDelegate.call(opts)
65
+ Attribute::CheckOptHashAccess.call(opts)
65
66
  Attribute::CheckOptHide.call(opts)
66
67
  Attribute::CheckOptMethod.call(opts)
67
68
  Attribute::CheckOptMany.call(opts, block)
data/lib/serega.rb CHANGED
@@ -29,6 +29,7 @@ require_relative "serega/utils/to_hash"
29
29
  require_relative "serega/attribute_value_resolvers/batch"
30
30
  require_relative "serega/attribute_value_resolvers/const"
31
31
  require_relative "serega/attribute_value_resolvers/delegate"
32
+ require_relative "serega/attribute_value_resolvers/hash_access"
32
33
  require_relative "serega/attribute_value_resolvers/keyword"
33
34
  require_relative "serega/attribute"
34
35
  require_relative "serega/attribute_normalizer"
@@ -46,6 +47,7 @@ require_relative "serega/validations/attribute/check_opt_const"
46
47
  require_relative "serega/validations/attribute/check_opt_hide"
47
48
  require_relative "serega/validations/attribute/check_opt_delegate"
48
49
  require_relative "serega/validations/attribute/check_opt_batch"
50
+ require_relative "serega/validations/attribute/check_opt_hash_access"
49
51
  require_relative "serega/validations/attribute/check_opt_many"
50
52
  require_relative "serega/validations/attribute/check_opt_method"
51
53
  require_relative "serega/validations/attribute/check_opt_preload"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serega
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.39.0
4
+ version: 0.40.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
@@ -32,6 +32,7 @@ files:
32
32
  - lib/serega/attribute_value_resolvers/batch.rb
33
33
  - lib/serega/attribute_value_resolvers/const.rb
34
34
  - lib/serega/attribute_value_resolvers/delegate.rb
35
+ - lib/serega/attribute_value_resolvers/hash_access.rb
35
36
  - lib/serega/attribute_value_resolvers/keyword.rb
36
37
  - lib/serega/config.rb
37
38
  - lib/serega/data_builder.rb
@@ -83,6 +84,7 @@ files:
83
84
  - lib/serega/validations/attribute/check_opt_batch.rb
84
85
  - lib/serega/validations/attribute/check_opt_const.rb
85
86
  - lib/serega/validations/attribute/check_opt_delegate.rb
87
+ - lib/serega/validations/attribute/check_opt_hash_access.rb
86
88
  - lib/serega/validations/attribute/check_opt_hide.rb
87
89
  - lib/serega/validations/attribute/check_opt_many.rb
88
90
  - lib/serega/validations/attribute/check_opt_method.rb