alba 1.3.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,7 @@
1
1
  module Alba
2
- # This module represents the inflector, which is used by default
2
+ # This module has two purposes.
3
+ # One is that we require `active_support/inflector` in this module so that we don't do that all over the place.
4
+ # Another is that `ActiveSupport::Inflector` doesn't have `camelize_lower` method that we want it to have, so this module works as an adapter.
3
5
  module DefaultInflector
4
6
  begin
5
7
  require 'active_support/inflector'
@@ -11,7 +13,7 @@ module Alba
11
13
 
12
14
  # Camelizes a key
13
15
  #
14
- # @params key [String] key to be camelized
16
+ # @param key [String] key to be camelized
15
17
  # @return [String] camelized key
16
18
  def camelize(key)
17
19
  ActiveSupport::Inflector.camelize(key)
@@ -19,7 +21,7 @@ module Alba
19
21
 
20
22
  # Camelizes a key, 1st letter lowercase
21
23
  #
22
- # @params key [String] key to be camelized
24
+ # @param key [String] key to be camelized
23
25
  # @return [String] camelized key
24
26
  def camelize_lower(key)
25
27
  ActiveSupport::Inflector.camelize(key, false)
@@ -27,10 +29,26 @@ module Alba
27
29
 
28
30
  # Dasherizes a key
29
31
  #
30
- # @params key [String] key to be dasherized
32
+ # @param key [String] key to be dasherized
31
33
  # @return [String] dasherized key
32
34
  def dasherize(key)
33
35
  ActiveSupport::Inflector.dasherize(key)
34
36
  end
37
+
38
+ # Underscore a key
39
+ #
40
+ # @param key [String] key to be underscore
41
+ # @return [String] underscored key
42
+ def underscore(key)
43
+ ActiveSupport::Inflector.underscore(key)
44
+ end
45
+
46
+ # Classify a key
47
+ #
48
+ # @param key [String] key to be classified
49
+ # @return [String] classified key
50
+ def classify(key)
51
+ ActiveSupport::Inflector.classify(key)
52
+ end
35
53
  end
36
54
  end
@@ -0,0 +1,14 @@
1
+ module Alba
2
+ # Module for printing deprecation warning
3
+ module Deprecation
4
+ # Similar to {Kernel.warn} but prints caller as well
5
+ #
6
+ # @param message [String] main message to print
7
+ # @return void
8
+ def warn(message)
9
+ Kernel.warn(message)
10
+ Kernel.warn(caller_locations(2..2).first) # For performance reason we use (2..2).first
11
+ end
12
+ module_function :warn
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ module Alba
2
+ # Base class for Errors
3
+ class Error < StandardError; end
4
+
5
+ # Error class for backend which is not supported
6
+ class UnsupportedBackend < Error; end
7
+
8
+ # Error class for type which is not supported
9
+ class UnsupportedType < Error; end
10
+ end
data/lib/alba/resource.rb CHANGED
@@ -1,14 +1,13 @@
1
- require_relative 'one'
2
- require_relative 'many'
3
- require_relative 'key_transform_factory'
1
+ require_relative 'association'
4
2
  require_relative 'typed_attribute'
3
+ require_relative 'deprecation'
5
4
 
6
5
  module Alba
7
6
  # This module represents what should be serialized
8
7
  module Resource
9
8
  # @!parse include InstanceMethods
10
9
  # @!parse extend ClassMethods
11
- DSLS = {_attributes: {}, _key: nil, _transform_key_function: nil, _transforming_root_key: false, _on_error: nil}.freeze
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
12
11
  private_constant :DSLS
13
12
 
14
13
  WITHIN_DEFAULT = Object.new.freeze
@@ -33,23 +32,33 @@ module Alba
33
32
 
34
33
  # @param object [Object] the object to be serialized
35
34
  # @param params [Hash] user-given Hash for arbitrary data
36
- # @param within [Hash] determines what associations to be serialized. If not set, it serializes all associations.
35
+ # @param within [Object, nil, false, true] determines what associations to be serialized. If not set, it serializes all associations.
37
36
  def initialize(object, params: {}, within: WITHIN_DEFAULT)
38
37
  @object = object
39
38
  @params = params.freeze
40
39
  @within = within
40
+ @method_existence = {} # Cache for `respond_to?` result
41
41
  DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.public_send(name)) }
42
42
  end
43
43
 
44
44
  # Serialize object into JSON string
45
45
  #
46
- # @param key [Symbol]
46
+ # @param key [Symbol, nil, true] DEPRECATED, use root_key instead
47
+ # @param root_key [Symbol, nil, true]
48
+ # @param meta [Hash] metadata for this seialization
47
49
  # @return [String] serialized JSON string
48
- def serialize(key: nil)
49
- key = key.nil? ? _key : key
50
- hash = key && key != '' ? {key.to_s => serializable_hash} : serializable_hash
51
- Alba.encoder.call(hash)
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)
52
60
  end
61
+ alias to_json serialize
53
62
 
54
63
  # A Hash for serialization
55
64
  #
@@ -57,127 +66,214 @@ module Alba
57
66
  def serializable_hash
58
67
  collection? ? @object.map(&converter) : converter.call(@object)
59
68
  end
60
- alias to_hash serializable_hash
69
+ alias to_h serializable_hash
70
+
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
61
76
 
62
77
  private
63
78
 
79
+ attr_reader :serialized_json # Mainly for layout
80
+
81
+ def encode(hash)
82
+ Alba.encoder.call(hash)
83
+ end
84
+
85
+ def serialize_with(hash)
86
+ serialized_json = encode(hash)
87
+ return serialized_json unless @_layout
88
+
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
106
+ end
107
+
108
+ def hash_with_metadata(hash, meta)
109
+ return hash if meta.empty? && @_meta.nil?
110
+
111
+ metadata = @_meta ? instance_eval(&@_meta).merge(meta) : meta
112
+ hash[:meta] = metadata
113
+ hash
114
+ end
115
+
116
+ def fetch_key
117
+ collection? ? _key_for_collection : _key
118
+ end
119
+
120
+ 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
125
+ end
126
+
64
127
  # @return [String]
65
128
  def _key
66
129
  return @_key.to_s unless @_key == true && Alba.inferring
67
130
 
68
- transforming_root_key? ? transform_key(key_from_resource_name) : key_from_resource_name
69
- end
70
-
71
- def key_from_resource_name
72
- collection? ? resource_name.pluralize : resource_name
131
+ transforming_root_key? ? transform_key(resource_name) : resource_name
73
132
  end
74
133
 
75
134
  def resource_name
76
- self.class.name.demodulize.delete_suffix('Resource').underscore
135
+ @resource_name ||= self.class.name.demodulize.delete_suffix('Resource').underscore
77
136
  end
78
137
 
79
138
  def transforming_root_key?
80
139
  @_transforming_root_key.nil? ? Alba.transforming_root_key : @_transforming_root_key
81
140
  end
82
141
 
142
+ # rubocop:disable Metrics/MethodLength
83
143
  def converter
84
144
  lambda do |object|
85
- arrays = @_attributes.map do |key, attribute|
145
+ arrays = attributes.map do |key, attribute|
86
146
  key_and_attribute_body_from(object, key, attribute)
87
147
  rescue ::Alba::Error, FrozenError, TypeError
88
148
  raise
89
149
  rescue StandardError => e
90
150
  handle_error(e, object, key, attribute)
91
151
  end
92
- arrays.reject(&:empty?).to_h
152
+ arrays.compact!
153
+ arrays.to_h
93
154
  end
94
155
  end
156
+ # rubocop:enable Metrics/MethodLength
157
+
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
95
163
 
96
164
  def key_and_attribute_body_from(object, key, attribute)
97
165
  key = transform_key(key)
98
166
  if attribute.is_a?(Array) # Conditional
99
167
  conditional_attribute(object, key, attribute)
100
168
  else
101
- [key, fetch_attribute(object, attribute)]
169
+ fetched_attribute = fetch_attribute(object, key, attribute)
170
+ [key, fetched_attribute]
102
171
  end
103
172
  end
104
173
 
105
174
  def conditional_attribute(object, key, attribute)
106
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)
180
+ end
181
+ end
182
+
183
+ def conditional_attribute_with_proc(object, key, attribute, condition)
107
184
  arity = condition.arity
108
- return [] if arity <= 1 && !instance_exec(object, &condition)
185
+ # We can return early to skip fetch_attribute
186
+ return if arity <= 1 && !instance_exec(object, &condition)
109
187
 
110
- fetched_attribute = fetch_attribute(object, attribute.first)
111
- attr = if attribute.first.is_a?(Alba::Association)
112
- attribute.first.object
113
- else
114
- fetched_attribute
115
- end
116
- return [] if arity >= 2 && !instance_exec(object, attr, &condition)
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)
117
191
 
118
192
  [key, fetched_attribute]
119
193
  end
120
194
 
195
+ def conditional_attribute_with_symbol(object, key, attribute, condition)
196
+ return unless __send__(condition)
197
+
198
+ [key, fetch_attribute(object, key, attribute)]
199
+ end
200
+
121
201
  def handle_error(error, object, key, attribute)
122
202
  on_error = @_on_error || Alba._on_error
123
203
  case on_error
124
- when :raise, nil
125
- raise
126
- when :nullify
127
- [key, nil]
128
- when :ignore
129
- []
130
- when Proc
131
- on_error.call(error, object, key, attribute, self.class)
204
+ when :raise, nil then raise
205
+ when :nullify then [key, nil]
206
+ when :ignore then nil
207
+ when Proc then on_error.call(error, object, key, attribute, self.class)
132
208
  else
133
209
  raise ::Alba::Error, "Unknown on_error: #{on_error.inspect}"
134
210
  end
135
211
  end
136
212
 
137
- # Override this method to supply custom key transform method
213
+ # rubocop:disable Metrics/MethodLength
214
+ # @return [Symbol]
138
215
  def transform_key(key)
139
- return key if @_transform_key_function.nil?
216
+ return key if @_transform_type == :none
217
+
218
+ 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
225
+ case @_transform_type # rubocop:disable Style/MissingElse
226
+ when :camel then inflector.camelize(key)
227
+ when :lower_camel then inflector.camelize_lower(key)
228
+ when :dash then inflector.dasherize(key)
229
+ when :snake then inflector.underscore(key)
230
+ end.to_sym
231
+ end
232
+ # rubocop:enable Metrics/MethodLength
233
+
234
+ def fetch_attribute(object, key, attribute)
235
+ value = case attribute
236
+ when Symbol then fetch_attribute_from_object_and_resource(object, attribute)
237
+ when Proc then instance_exec(object, &attribute)
238
+ 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)
240
+ else
241
+ raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
242
+ end
243
+ value.nil? && nil_handler ? instance_exec(object, key, attribute, &nil_handler) : value
244
+ end
140
245
 
141
- @_transform_key_function.call(key.to_s)
246
+ def fetch_attribute_from_object_and_resource(object, attribute)
247
+ has_method = @method_existence[attribute]
248
+ has_method = @method_existence[attribute] = object.respond_to?(attribute) if has_method.nil?
249
+ has_method ? object.public_send(attribute) : __send__(attribute, object)
142
250
  end
143
251
 
144
- def fetch_attribute(object, attribute)
145
- case attribute
146
- when Symbol
147
- object.public_send attribute
148
- when Proc
149
- instance_exec(object, &attribute)
150
- when Alba::One, Alba::Many
151
- within = check_within(attribute.name.to_sym)
152
- return unless within
252
+ def nil_handler
253
+ @nil_handler ||= (@_on_nil || Alba._on_nil)
254
+ end
153
255
 
154
- attribute.to_hash(object, params: params, within: within)
155
- when TypedAttribute
156
- attribute.value(object)
157
- else
158
- raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
159
- end
256
+ def yield_if_within(association_name)
257
+ within = check_within(association_name)
258
+ yield(within) if within
160
259
  end
161
260
 
162
261
  def check_within(association_name)
163
262
  case @within
164
- when WITHIN_DEFAULT # Default value, doesn't check within tree
165
- WITHIN_DEFAULT
166
- when Hash # Traverse within tree
167
- @within.fetch(association_name, nil)
168
- when Array # within tree ends with Array
169
- @within.find { |item| item.to_sym == association_name }
170
- when Symbol # within tree could end with Symbol
171
- @within == association_name
172
- when nil, true, false # In these cases, Alba stops serialization here.
173
- false
263
+ when WITHIN_DEFAULT then WITHIN_DEFAULT # Default value, doesn't check within tree
264
+ when Hash then @within.fetch(association_name, nil) # Traverse within tree
265
+ when Array then @within.find { |item| item.to_sym == association_name }
266
+ when Symbol then @within == association_name
267
+ when nil, true, false then false # Stop here
174
268
  else
175
269
  raise Alba::Error, "Unknown type for within option: #{@within.class}"
176
270
  end
177
271
  end
178
272
 
273
+ # Detect if object is a collection or not.
274
+ # When object is a Struct, it's Enumerable but not a collection
179
275
  def collection?
180
- @object.is_a?(Enumerable)
276
+ @object.is_a?(Enumerable) && !@object.is_a?(Struct)
181
277
  end
182
278
  end
183
279
 
@@ -191,11 +287,15 @@ module Alba
191
287
  DSLS.each_key { |name| subclass.instance_variable_set("@#{name}", instance_variable_get("@#{name}").clone) }
192
288
  end
193
289
 
290
+ # Defining methods for DSLs and disable parameter number check since for users' benefits increasing params is fine
291
+
194
292
  # Set multiple attributes at once
195
293
  #
196
294
  # @param attrs [Array<String, Symbol>]
197
- # @param if [Boolean] condition to decide if it should render these attributes
198
- # @param attrs_with_types [Hash] attributes with name in its key and type and optional type converter in its value
295
+ # @param if [Proc] condition to decide if it should serialize these attributes
296
+ # @param attrs_with_types [Hash<[Symbol, String], [Array<Symbol, Proc>, Symbol]>]
297
+ # attributes with name in its key and type and optional type converter in its value
298
+ # @return [void]
199
299
  def attributes(*attrs, if: nil, **attrs_with_types) # rubocop:disable Naming/MethodParameterName
200
300
  if_value = binding.local_variable_get(:if)
201
301
  assign_attributes(attrs, if_value)
@@ -224,65 +324,109 @@ module Alba
224
324
  # Set an attribute with the given block
225
325
  #
226
326
  # @param name [String, Symbol] key name
227
- # @param options [Hash] option hash including `if` that is a condition to render
327
+ # @param options [Hash<Symbol, Proc>]
328
+ # @option options [Proc] if a condition to decide if this attribute should be serialized
228
329
  # @param block [Block] the block called during serialization
229
330
  # @raise [ArgumentError] if block is absent
331
+ # @return [void]
230
332
  def attribute(name, **options, &block)
231
333
  raise ArgumentError, 'No block given in attribute method' unless block
232
334
 
233
335
  @_attributes[name.to_sym] = options[:if] ? [block, options[:if]] : block
234
336
  end
235
337
 
236
- # Set One association
237
- #
238
- # @param name [String, Symbol]
239
- # @param condition [Proc]
240
- # @param resource [Class<Alba::Resource>]
241
- # @param key [String, Symbol] used as key when given
242
- # @param options [Hash] option hash including `if` that is a condition to render
243
- # @param block [Block]
244
- # @see Alba::One#initialize
245
- def one(name, condition = nil, resource: nil, key: nil, **options, &block)
246
- nesting = self.name&.rpartition('::')&.first
247
- one = One.new(name: name, condition: condition, resource: resource, nesting: nesting, &block)
248
- @_attributes[key&.to_sym || name.to_sym] = options[:if] ? [one, options[:if]] : one
249
- end
250
- alias has_one one
251
-
252
- # Set Many association
338
+ # Set association
253
339
  #
254
- # @param name [String, Symbol]
255
- # @param condition [Proc]
256
- # @param resource [Class<Alba::Resource>]
257
- # @param key [String, Symbol] used as key when given
258
- # @param options [Hash] option hash including `if` that is a condition to render
340
+ # @param name [String, Symbol] name of the association, used as key when `key` param doesn't exist
341
+ # @param condition [Proc, nil] a Proc to modify the association
342
+ # @param resource [Class<Alba::Resource>, String, nil] representing resource for this association
343
+ # @param key [String, Symbol, nil] used as key when given
344
+ # @param options [Hash<Symbol, Proc>]
345
+ # @option options [Proc] if a condition to decide if this association should be serialized
259
346
  # @param block [Block]
260
- # @see Alba::Many#initialize
261
- def many(name, condition = nil, resource: nil, key: nil, **options, &block)
347
+ # @return [void]
348
+ # @see Alba::Association#initialize
349
+ def association(name, condition = nil, resource: nil, key: nil, **options, &block)
262
350
  nesting = self.name&.rpartition('::')&.first
263
- many = Many.new(name: name, condition: condition, resource: resource, nesting: nesting, &block)
264
- @_attributes[key&.to_sym || name.to_sym] = options[:if] ? [many, options[:if]] : many
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
265
353
  end
266
- alias has_many many
354
+ alias one association
355
+ alias many association
356
+ alias has_one association
357
+ alias has_many association
267
358
 
268
359
  # Set key
269
360
  #
270
361
  # @param key [String, Symbol]
362
+ # @deprecated Use {#root_key} instead
271
363
  def key(key)
364
+ Alba::Deprecation.warn '[DEPRECATION] `key` is deprecated, use `root_key` instead.'
272
365
  @_key = key.respond_to?(:to_sym) ? key.to_sym : key
273
366
  end
274
367
 
368
+ # Set root key
369
+ #
370
+ # @param key [String, Symbol]
371
+ # @param key_for_collection [String, Symbol]
372
+ # @raise [NoMethodError] when key doesn't respond to `to_sym` method
373
+ def root_key(key, key_for_collection = nil)
374
+ @_key = key.to_sym
375
+ @_key_for_collection = key_for_collection&.to_sym
376
+ end
377
+
275
378
  # Set key to true
276
379
  #
380
+ # @deprecated Use {#root_key!} instead
277
381
  def key!
382
+ Alba::Deprecation.warn '[DEPRECATION] `key!` is deprecated, use `root_key!` instead.'
278
383
  @_key = true
384
+ @_key_for_collection = true
279
385
  end
280
386
 
387
+ # Set root key to true
388
+ def root_key!
389
+ @_key = true
390
+ @_key_for_collection = true
391
+ end
392
+
393
+ # Set metadata
394
+ def meta(&block)
395
+ @_meta = block
396
+ end
397
+
398
+ # Set layout
399
+ #
400
+ # @params file [String] name of the layout file
401
+ # @params inline [Proc] a proc returning JSON string or a Hash representing JSON
402
+ 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
+
281
424
  # Delete attributes
282
425
  # Use this DSL in child class to ignore certain attributes
283
426
  #
284
427
  # @param attributes [Array<String, Symbol>]
285
428
  def ignoring(*attributes)
429
+ Alba::Deprecation.warn '`ignoring` is deprecated now. Instead please use `attributes` instance method to filter out attributes.'
286
430
  attributes.each do |attr_name|
287
431
  @_attributes.delete(attr_name.to_sym)
288
432
  end
@@ -290,23 +434,39 @@ module Alba
290
434
 
291
435
  # Transform keys as specified type
292
436
  #
293
- # @param type [String, Symbol]
294
- # @param root [Boolean] decides if root key also should be transformed
437
+ # @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
440
+ # @raise [Alba::Error] when type is not supported
295
441
  def transform_keys(type, root: nil)
296
- @_transform_key_function = KeyTransformFactory.create(type.to_sym)
442
+ type = type.to_sym
443
+ unless %i[none snake camel lower_camel dash].include?(type)
444
+ # This should be `ArgumentError` but for backward compatibility it raises `Alba::Error`
445
+ raise ::Alba::Error, "Unknown transform type: #{type}. Supported type are :camel, :lower_camel and :dash."
446
+ end
447
+
448
+ @_transform_type = type
297
449
  @_transforming_root_key = root
298
450
  end
299
451
 
300
452
  # Set error handler
453
+ # If this is set it's used as a error handler overriding global one
301
454
  #
302
- # @param [Symbol] handler
303
- # @param [Block]
455
+ # @param handler [Symbol] `:raise`, `:ignore` or `:nullify`
456
+ # @param block [Block]
304
457
  def on_error(handler = nil, &block)
305
458
  raise ArgumentError, 'You cannot specify error handler with both Symbol and block' if handler && block
306
459
  raise ArgumentError, 'You must specify error handler with either Symbol or block' unless handler || block
307
460
 
308
461
  @_on_error = handler || block
309
462
  end
463
+
464
+ # Set nil handler
465
+ #
466
+ # @param block [Block]
467
+ def on_nil(&block)
468
+ @_on_nil = block
469
+ end
310
470
  end
311
471
  end
312
472
  end
@@ -28,12 +28,9 @@ module Alba
28
28
  def check(object)
29
29
  value = object.public_send(@name)
30
30
  type_correct = case @type
31
- when :String, ->(klass) { klass == String }
32
- value.is_a?(String)
33
- when :Integer, ->(klass) { klass == Integer }
34
- value.is_a?(Integer)
35
- when :Boolean
36
- [true, false].include?(value)
31
+ when :String, ->(klass) { klass == String } then value.is_a?(String)
32
+ when :Integer, ->(klass) { klass == Integer } then value.is_a?(Integer)
33
+ when :Boolean then [true, false].include?(value)
37
34
  else
38
35
  raise Alba::UnsupportedType, "Unknown type: #{@type}"
39
36
  end
data/lib/alba/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Alba
2
- VERSION = '1.3.0'.freeze
2
+ VERSION = '1.6.0'.freeze
3
3
  end