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