alba 1.6.0 → 2.0.1

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.
data/lib/alba/resource.rb CHANGED
@@ -1,13 +1,17 @@
1
1
  require_relative 'association'
2
+ require_relative 'conditional_attribute'
3
+ require_relative 'constants'
2
4
  require_relative 'typed_attribute'
5
+ require_relative 'nested_attribute'
3
6
  require_relative 'deprecation'
7
+ require_relative 'layout'
4
8
 
5
9
  module Alba
6
10
  # This module represents what should be serialized
7
11
  module Resource
8
12
  # @!parse include InstanceMethods
9
13
  # @!parse extend ClassMethods
10
- DSLS = {_attributes: {}, _key: nil, _key_for_collection: nil, _meta: nil, _transform_type: :none, _transforming_root_key: false, _on_error: nil, _on_nil: nil, _layout: nil}.freeze # rubocop:disable Layout/LineLength
14
+ DSLS = {_attributes: {}, _key: nil, _key_for_collection: nil, _meta: nil, _transform_type: :none, _transforming_root_key: false, _on_error: nil, _on_nil: nil, _layout: nil, _collection_key: nil}.freeze # rubocop:disable Layout/LineLength
11
15
  private_constant :DSLS
12
16
 
13
17
  WITHIN_DEFAULT = Object.new.freeze
@@ -35,74 +39,91 @@ module Alba
35
39
  # @param within [Object, nil, false, true] determines what associations to be serialized. If not set, it serializes all associations.
36
40
  def initialize(object, params: {}, within: WITHIN_DEFAULT)
37
41
  @object = object
38
- @params = params.freeze
42
+ @params = params
39
43
  @within = within
40
44
  @method_existence = {} # Cache for `respond_to?` result
41
- DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.public_send(name)) }
45
+ DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.__send__(name)) }
42
46
  end
43
47
 
44
48
  # Serialize object into JSON string
45
49
  #
46
- # @param key [Symbol, nil, true] DEPRECATED, use root_key instead
47
50
  # @param root_key [Symbol, nil, true]
48
51
  # @param meta [Hash] metadata for this seialization
49
52
  # @return [String] serialized JSON string
50
- def serialize(key: nil, root_key: nil, meta: {})
51
- Alba::Deprecation.warn '`key` option to `serialize` method is deprecated, use `root_key` instead.' if key
52
- key = key.nil? && root_key.nil? ? fetch_key : root_key || key
53
- hash = if key && key != ''
54
- h = {key.to_s => serializable_hash}
55
- hash_with_metadata(h, meta)
56
- else
57
- serializable_hash
58
- end
59
- serialize_with(hash)
60
- end
61
- alias to_json serialize
53
+ def serialize(root_key: nil, meta: {})
54
+ serialize_with(as_json(root_key: root_key, meta: meta))
55
+ end
56
+
57
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.0')
58
+ # For Rails compatibility
59
+ # The first options is a dummy parameter but required
60
+ # You can pass empty Hash if you don't want to pass any arguments
61
+ #
62
+ # @see #serialize
63
+ # @see https://github.com/rails/rails/blob/7-0-stable/actionpack/lib/action_controller/metal/renderers.rb#L156
64
+ def to_json(options, root_key: nil, meta: {})
65
+ _to_json(root_key, meta, options)
66
+ end
67
+ else
68
+ # For Rails compatibility
69
+ # The first options is a dummy parameter
70
+ #
71
+ # @see #serialize
72
+ # @see https://github.com/rails/rails/blob/7-0-stable/actionpack/lib/action_controller/metal/renderers.rb#L156
73
+ def to_json(options = {}, root_key: nil, meta: {})
74
+ _to_json(root_key, meta, options)
75
+ end
76
+ end
77
+
78
+ # Returns a Hash correspondng {Resource#serialize}
79
+ #
80
+ # @param root_key [Symbol, nil, true]
81
+ # @param meta [Hash] metadata for this seialization
82
+ # @param symbolize_root_key [Boolean] determines if root key should be symbolized
83
+ # @return [Hash]
84
+ def as_json(root_key: nil, meta: {})
85
+ key = root_key.nil? ? fetch_key : root_key.to_s
86
+ if key && !key.empty?
87
+ h = {key => serializable_hash}
88
+ hash_with_metadata(h, meta)
89
+ else
90
+ serializable_hash
91
+ end
92
+ end
62
93
 
63
94
  # A Hash for serialization
64
95
  #
65
96
  # @return [Hash]
66
97
  def serializable_hash
67
- collection? ? @object.map(&converter) : converter.call(@object)
98
+ collection? ? serializable_hash_for_collection : converter.call(@object)
68
99
  end
69
100
  alias to_h serializable_hash
70
101
 
71
- # @deprecated Use {#serializable_hash} instead
72
- def to_hash
73
- warn '[DEPRECATION] `to_hash` is deprecated, use `serializable_hash` instead.'
74
- serializable_hash
75
- end
76
-
77
102
  private
78
103
 
79
- attr_reader :serialized_json # Mainly for layout
80
-
81
104
  def encode(hash)
82
105
  Alba.encoder.call(hash)
83
106
  end
84
107
 
108
+ def _to_json(root_key, meta, options)
109
+ options.reject! { |k, _| %i[layout prefixes template status].include?(k) } # Rails specific guard
110
+ # TODO: use `filter_map` after dropping support of Ruby 2.6
111
+ names = options.map { |k, v| k unless v.nil? }
112
+ names.compact!
113
+ unless names.empty?
114
+ names.sort!
115
+ names.map! { |s| "\"#{s}\"" }
116
+ message = "You passed #{names.join(', ')} options but ignored. Please refer to the document: https://github.com/okuramasafumi/alba/blob/main/docs/rails.md"
117
+ Kernel.warn(message)
118
+ end
119
+ serialize(root_key: root_key, meta: meta)
120
+ end
121
+
85
122
  def serialize_with(hash)
86
123
  serialized_json = encode(hash)
87
124
  return serialized_json unless @_layout
88
125
 
89
- @serialized_json = serialized_json
90
- if @_layout.is_a?(String) # file
91
- ERB.new(File.read(@_layout)).result(binding)
92
-
93
- else # inline
94
- serialize_within_inline_layout
95
- end
96
- end
97
-
98
- def serialize_within_inline_layout
99
- inline = instance_eval(&@_layout)
100
- case inline
101
- when Hash then encode(inline)
102
- when String then inline
103
- else
104
- raise Alba::Error, 'Inline layout must be a Proc returning a Hash or a String'
105
- end
126
+ @_layout.serialize(resource: self, serialized_json: serialized_json, binding: binding)
106
127
  end
107
128
 
108
129
  def hash_with_metadata(hash, meta)
@@ -113,130 +134,126 @@ module Alba
113
134
  hash
114
135
  end
115
136
 
137
+ def serializable_hash_for_collection
138
+ if @_collection_key
139
+ @object.to_h { |item| [item.public_send(@_collection_key).to_s, converter.call(item)] }
140
+ else
141
+ @object.each_with_object([], &collection_converter)
142
+ end
143
+ end
144
+
145
+ # @return [String]
116
146
  def fetch_key
117
- collection? ? _key_for_collection : _key
147
+ k = collection? ? _key_for_collection : _key
148
+ transforming_root_key? ? transform_key(k) : k
118
149
  end
119
150
 
120
151
  def _key_for_collection
121
- return @_key_for_collection.to_s unless @_key_for_collection == true && Alba.inferring
122
-
123
- key = resource_name.pluralize
124
- transforming_root_key? ? transform_key(key) : key
152
+ if Alba.inferring
153
+ @_key_for_collection == true ? resource_name(pluralized: true) : @_key_for_collection.to_s
154
+ else
155
+ @_key_for_collection == true ? raise_root_key_inference_error : @_key_for_collection.to_s
156
+ end
125
157
  end
126
158
 
127
159
  # @return [String]
128
160
  def _key
129
- return @_key.to_s unless @_key == true && Alba.inferring
161
+ if Alba.inferring
162
+ @_key == true ? resource_name(pluralized: false) : @_key.to_s
163
+ else
164
+ @_key == true ? raise_root_key_inference_error : @_key.to_s
165
+ end
166
+ end
130
167
 
131
- transforming_root_key? ? transform_key(resource_name) : resource_name
168
+ def resource_name(pluralized: false)
169
+ class_name = self.class.name
170
+ inflector = Alba.inflector
171
+ name = inflector.demodulize(class_name).delete_suffix('Resource')
172
+ underscore_name = inflector.underscore(name)
173
+ pluralized ? inflector.pluralize(underscore_name) : underscore_name
132
174
  end
133
175
 
134
- def resource_name
135
- @resource_name ||= self.class.name.demodulize.delete_suffix('Resource').underscore
176
+ def raise_root_key_inference_error
177
+ raise Alba::Error, 'You must call Alba.enable_inference! to set root_key to true for inferring root key.'
136
178
  end
137
179
 
138
180
  def transforming_root_key?
139
- @_transforming_root_key.nil? ? Alba.transforming_root_key : @_transforming_root_key
181
+ @_transforming_root_key
140
182
  end
141
183
 
142
- # rubocop:disable Metrics/MethodLength
143
184
  def converter
144
185
  lambda do |object|
145
- arrays = attributes.map do |key, attribute|
146
- key_and_attribute_body_from(object, key, attribute)
147
- rescue ::Alba::Error, FrozenError, TypeError
148
- raise
149
- rescue StandardError => e
150
- handle_error(e, object, key, attribute)
151
- end
152
- arrays.compact!
153
- arrays.to_h
186
+ attributes_to_hash(object, {})
154
187
  end
155
188
  end
156
- # rubocop:enable Metrics/MethodLength
157
189
 
158
- # This is default behavior for getting attributes for serialization
159
- # Override this method to filter certain attributes
160
- def attributes
161
- @_attributes
162
- end
163
-
164
- def key_and_attribute_body_from(object, key, attribute)
165
- key = transform_key(key)
166
- if attribute.is_a?(Array) # Conditional
167
- conditional_attribute(object, key, attribute)
168
- else
169
- fetched_attribute = fetch_attribute(object, key, attribute)
170
- [key, fetched_attribute]
190
+ def collection_converter
191
+ lambda do |object, a|
192
+ a << {}
193
+ h = a.last
194
+ attributes_to_hash(object, h)
195
+ a
171
196
  end
172
197
  end
173
198
 
174
- def conditional_attribute(object, key, attribute)
175
- condition = attribute.last
176
- if condition.is_a?(Proc)
177
- conditional_attribute_with_proc(object, key, attribute.first, condition)
178
- else
179
- conditional_attribute_with_symbol(object, key, attribute.first, condition)
199
+ def attributes_to_hash(object, hash)
200
+ attributes.each do |key, attribute|
201
+ set_key_and_attribute_body_from(object, key, attribute, hash)
202
+ rescue ::Alba::Error, FrozenError, TypeError
203
+ raise
204
+ rescue StandardError => e
205
+ handle_error(e, object, key, attribute, hash)
180
206
  end
207
+ hash
181
208
  end
182
209
 
183
- def conditional_attribute_with_proc(object, key, attribute, condition)
184
- arity = condition.arity
185
- # We can return early to skip fetch_attribute
186
- return if arity <= 1 && !instance_exec(object, &condition)
187
-
188
- fetched_attribute = fetch_attribute(object, key, attribute)
189
- attr = attribute.is_a?(Alba::Association) ? attribute.object : fetched_attribute
190
- return if arity >= 2 && !instance_exec(object, attr, &condition)
191
-
192
- [key, fetched_attribute]
210
+ # This is default behavior for getting attributes for serialization
211
+ # Override this method to filter certain attributes
212
+ def attributes
213
+ @_attributes
193
214
  end
194
215
 
195
- def conditional_attribute_with_symbol(object, key, attribute, condition)
196
- return unless __send__(condition)
197
-
198
- [key, fetch_attribute(object, key, attribute)]
216
+ def set_key_and_attribute_body_from(object, key, attribute, hash)
217
+ key = transform_key(key)
218
+ value = fetch_attribute(object, key, attribute)
219
+ hash[key] = value unless value == Alba::REMOVE_KEY
199
220
  end
200
221
 
201
- def handle_error(error, object, key, attribute)
202
- on_error = @_on_error || Alba._on_error
203
- case on_error
204
- when :raise, nil then raise
205
- when :nullify then [key, nil]
222
+ def handle_error(error, object, key, attribute, hash)
223
+ on_error = @_on_error || :raise
224
+ case on_error # rubocop:disable Style/MissingElse
225
+ when :raise, nil then raise(error)
226
+ when :nullify then hash[key] = nil
206
227
  when :ignore then nil
207
- when Proc then on_error.call(error, object, key, attribute, self.class)
208
- else
209
- raise ::Alba::Error, "Unknown on_error: #{on_error.inspect}"
228
+ when Proc
229
+ key, value = on_error.call(error, object, key, attribute, self.class)
230
+ hash[key] = value
210
231
  end
211
232
  end
212
233
 
213
- # rubocop:disable Metrics/MethodLength
214
234
  # @return [Symbol]
215
- def transform_key(key)
216
- return key if @_transform_type == :none
217
-
235
+ def transform_key(key) # rubocop:disable Metrics/CyclomaticComplexity
218
236
  key = key.to_s
219
- # TODO: Using default inflector here is for backward compatibility
220
- # From 2.0 it'll raise error when inflector is nil
221
- inflector = Alba.inflector || begin
222
- require_relative 'default_inflector'
223
- Alba::DefaultInflector
224
- end
237
+ return key if @_transform_type == :none || key.empty? # We can skip transformation
238
+
239
+ inflector = Alba.inflector
240
+ raise Alba::Error, 'Inflector is nil. You can set inflector with `Alba.enable_inference!(with: :active_support)` for example.' unless inflector
241
+
225
242
  case @_transform_type # rubocop:disable Style/MissingElse
226
243
  when :camel then inflector.camelize(key)
227
244
  when :lower_camel then inflector.camelize_lower(key)
228
245
  when :dash then inflector.dasherize(key)
229
246
  when :snake then inflector.underscore(key)
230
- end.to_sym
247
+ end
231
248
  end
232
- # rubocop:enable Metrics/MethodLength
233
249
 
234
- def fetch_attribute(object, key, attribute)
250
+ def fetch_attribute(object, key, attribute) # rubocop:disable Metrics/CyclomaticComplexity
235
251
  value = case attribute
236
252
  when Symbol then fetch_attribute_from_object_and_resource(object, attribute)
237
253
  when Proc then instance_exec(object, &attribute)
238
254
  when Alba::Association then yield_if_within(attribute.name.to_sym) { |within| attribute.to_h(object, params: params, within: within) }
239
- when TypedAttribute then attribute.value(object)
255
+ when TypedAttribute, NestedAttribute then attribute.value(object)
256
+ when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: object) { |attr| fetch_attribute(object, key, attr) }
240
257
  else
241
258
  raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
242
259
  end
@@ -246,16 +263,16 @@ module Alba
246
263
  def fetch_attribute_from_object_and_resource(object, attribute)
247
264
  has_method = @method_existence[attribute]
248
265
  has_method = @method_existence[attribute] = object.respond_to?(attribute) if has_method.nil?
249
- has_method ? object.public_send(attribute) : __send__(attribute, object)
266
+ has_method ? object.__send__(attribute) : __send__(attribute, object)
250
267
  end
251
268
 
252
269
  def nil_handler
253
- @nil_handler ||= (@_on_nil || Alba._on_nil)
270
+ @_on_nil
254
271
  end
255
272
 
256
273
  def yield_if_within(association_name)
257
274
  within = check_within(association_name)
258
- yield(within) if within
275
+ within ? yield(within) : Alba::REMOVE_KEY
259
276
  end
260
277
 
261
278
  def check_within(association_name)
@@ -304,7 +321,7 @@ module Alba
304
321
 
305
322
  def assign_attributes(attrs, if_value)
306
323
  attrs.each do |attr_name|
307
- attr = if_value ? [attr_name.to_sym, if_value] : attr_name.to_sym
324
+ attr = if_value ? ConditionalAttribute.new(body: attr_name.to_sym, condition: if_value) : attr_name.to_sym
308
325
  @_attributes[attr_name.to_sym] = attr
309
326
  end
310
327
  end
@@ -315,7 +332,7 @@ module Alba
315
332
  attr_name = attr_name.to_sym
316
333
  type, type_converter = type_and_converter
317
334
  typed_attr = TypedAttribute.new(name: attr_name, type: type, converter: type_converter)
318
- attr = if_value ? [typed_attr, if_value] : typed_attr
335
+ attr = if_value ? ConditionalAttribute.new(body: typed_attr, condition: if_value) : typed_attr
319
336
  @_attributes[attr_name] = attr
320
337
  end
321
338
  end
@@ -332,38 +349,59 @@ module Alba
332
349
  def attribute(name, **options, &block)
333
350
  raise ArgumentError, 'No block given in attribute method' unless block
334
351
 
335
- @_attributes[name.to_sym] = options[:if] ? [block, options[:if]] : block
352
+ @_attributes[name.to_sym] = options[:if] ? ConditionalAttribute.new(body: block, condition: options[:if]) : block
336
353
  end
337
354
 
338
355
  # Set association
339
356
  #
340
357
  # @param name [String, Symbol] name of the association, used as key when `key` param doesn't exist
341
358
  # @param condition [Proc, nil] a Proc to modify the association
342
- # @param resource [Class<Alba::Resource>, String, nil] representing resource for this association
359
+ # @param resource [Class<Alba::Resource>, String, Proc, nil] representing resource for this association
343
360
  # @param key [String, Symbol, nil] used as key when given
361
+ # @param params [Hash] params override for the association
344
362
  # @param options [Hash<Symbol, Proc>]
345
363
  # @option options [Proc] if a condition to decide if this association should be serialized
346
364
  # @param block [Block]
347
365
  # @return [void]
348
366
  # @see Alba::Association#initialize
349
- def association(name, condition = nil, resource: nil, key: nil, **options, &block)
350
- nesting = self.name&.rpartition('::')&.first
351
- assoc = Association.new(name: name, condition: condition, resource: resource, nesting: nesting, &block)
352
- @_attributes[key&.to_sym || name.to_sym] = options[:if] ? [assoc, options[:if]] : assoc
367
+ def association(name, condition = nil, resource: nil, key: nil, params: {}, **options, &block)
368
+ key_transformation = @_key_transformation_cascade ? @_transform_type : :none
369
+ assoc = Association.new(
370
+ name: name, condition: condition, resource: resource, params: params, nesting: nesting, key_transformation: key_transformation,
371
+ &block
372
+ )
373
+ @_attributes[key&.to_sym || name.to_sym] = options[:if] ? ConditionalAttribute.new(body: assoc, condition: options[:if]) : assoc
353
374
  end
354
375
  alias one association
355
376
  alias many association
356
377
  alias has_one association
357
378
  alias has_many association
358
379
 
359
- # Set key
380
+ def nesting
381
+ if name.nil?
382
+ nil
383
+ else
384
+ name.rpartition('::').first.tap { |n| n.empty? ? nil : n }
385
+ end
386
+ end
387
+ private :nesting
388
+
389
+ # Set a nested attribute with the given block
360
390
  #
361
- # @param key [String, Symbol]
362
- # @deprecated Use {#root_key} instead
363
- def key(key)
364
- Alba::Deprecation.warn '[DEPRECATION] `key` is deprecated, use `root_key` instead.'
365
- @_key = key.respond_to?(:to_sym) ? key.to_sym : key
391
+ # @param name [String, Symbol] key name
392
+ # @param options [Hash<Symbol, Proc>]
393
+ # @option options [Proc] if a condition to decide if this attribute should be serialized
394
+ # @param block [Block] the block called during serialization
395
+ # @raise [ArgumentError] if block is absent
396
+ # @return [void]
397
+ def nested_attribute(name, **options, &block)
398
+ raise ArgumentError, 'No block given in attribute method' unless block
399
+
400
+ key_transformation = @_key_transformation_cascade ? @_transform_type : :none
401
+ attribute = NestedAttribute.new(key_transformation: key_transformation, &block)
402
+ @_attributes[name.to_sym] = options[:if] ? ConditionalAttribute.new(body: attribute, condition: options[:if]) : attribute
366
403
  end
404
+ alias nested nested_attribute
367
405
 
368
406
  # Set root key
369
407
  #
@@ -375,13 +413,13 @@ module Alba
375
413
  @_key_for_collection = key_for_collection&.to_sym
376
414
  end
377
415
 
378
- # Set key to true
416
+ # Set root key for collection
379
417
  #
380
- # @deprecated Use {#root_key!} instead
381
- def key!
382
- Alba::Deprecation.warn '[DEPRECATION] `key!` is deprecated, use `root_key!` instead.'
418
+ # @param key [String, Symbol]
419
+ # @raise [NoMethodError] when key doesn't respond to `to_sym` method
420
+ def root_key_for_collection(key)
383
421
  @_key = true
384
- @_key_for_collection = true
422
+ @_key_for_collection = key.to_sym
385
423
  end
386
424
 
387
425
  # Set root key to true
@@ -400,45 +438,17 @@ module Alba
400
438
  # @params file [String] name of the layout file
401
439
  # @params inline [Proc] a proc returning JSON string or a Hash representing JSON
402
440
  def layout(file: nil, inline: nil)
403
- @_layout = validated_file_layout(file) || validated_inline_layout(inline)
404
- end
405
-
406
- def validated_file_layout(filename)
407
- case filename
408
- when String, nil then filename
409
- else
410
- raise ArgumentError, 'File layout must be a String representing filename'
411
- end
412
- end
413
- private :validated_file_layout
414
-
415
- def validated_inline_layout(inline_layout)
416
- case inline_layout
417
- when Proc, nil then inline_layout
418
- else
419
- raise ArgumentError, 'Inline layout must be a Proc returning a Hash or a String'
420
- end
421
- end
422
- private :validated_inline_layout
423
-
424
- # Delete attributes
425
- # Use this DSL in child class to ignore certain attributes
426
- #
427
- # @param attributes [Array<String, Symbol>]
428
- def ignoring(*attributes)
429
- Alba::Deprecation.warn '`ignoring` is deprecated now. Instead please use `attributes` instance method to filter out attributes.'
430
- attributes.each do |attr_name|
431
- @_attributes.delete(attr_name.to_sym)
432
- end
441
+ @_layout = Layout.new(file: file, inline: inline)
433
442
  end
434
443
 
435
444
  # Transform keys as specified type
436
445
  #
437
446
  # @param type [String, Symbol] one of `snake`, `:camel`, `:lower_camel`, `:dash` and `none`
438
- # @param root [Boolean, nil] decides if root key also should be transformed
439
- # When it's `nil`, Alba's default setting will be applied
447
+ # @param root [Boolean] decides if root key also should be transformed
448
+ # @param cascade [Boolean] decides if key transformation cascades into inline association
449
+ # Default is true but can be set false for old (v1) behavior
440
450
  # @raise [Alba::Error] when type is not supported
441
- def transform_keys(type, root: nil)
451
+ def transform_keys(type, root: true, cascade: true)
442
452
  type = type.to_sym
443
453
  unless %i[none snake camel lower_camel dash].include?(type)
444
454
  # This should be `ArgumentError` but for backward compatibility it raises `Alba::Error`
@@ -447,6 +457,14 @@ module Alba
447
457
 
448
458
  @_transform_type = type
449
459
  @_transforming_root_key = root
460
+ @_key_transformation_cascade = cascade
461
+ end
462
+
463
+ # Sets key for collection serialization
464
+ #
465
+ # @param key [String, Symbol]
466
+ def collection_key(key)
467
+ @_collection_key = key.to_sym
450
468
  end
451
469
 
452
470
  # Set error handler
@@ -458,8 +476,19 @@ module Alba
458
476
  raise ArgumentError, 'You cannot specify error handler with both Symbol and block' if handler && block
459
477
  raise ArgumentError, 'You must specify error handler with either Symbol or block' unless handler || block
460
478
 
461
- @_on_error = handler || block
479
+ @_on_error = block || validated_error_handler(handler)
480
+ end
481
+
482
+ def validated_error_handler(handler)
483
+ unless %i[raise ignore nullify].include?(handler)
484
+ # For backward compatibility
485
+ # TODO: Change this to ArgumentError
486
+ raise Alba::Error, "Unknown error handler: #{handler}. It must be one of `:raise`, `:ignore` or `:nullify`."
487
+ end
488
+
489
+ handler
462
490
  end
491
+ private :validated_error_handler
463
492
 
464
493
  # Set nil handler
465
494
  #
@@ -26,7 +26,7 @@ module Alba
26
26
  private
27
27
 
28
28
  def check(object)
29
- value = object.public_send(@name)
29
+ value = object.__send__(@name)
30
30
  type_correct = case @type
31
31
  when :String, ->(klass) { klass == String } then value.is_a?(String)
32
32
  when :Integer, ->(klass) { klass == Integer } then value.is_a?(Integer)
data/lib/alba/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Alba
2
- VERSION = '1.6.0'.freeze
2
+ VERSION = '2.0.1'.freeze
3
3
  end