alba 3.9.1 → 3.10.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: ce994ee53f2a5f9291096f897469bd131c5f925560a0cd13690247d1278b9310
4
- data.tar.gz: cbcc9e5e031fc52c20560fa0d8f06465728e5825a08a36d50d6d26f5f1ca4a3a
3
+ metadata.gz: 12a2e005c86ae86d746947d98732a5931340e378e0557a34de97d0eee533dff1
4
+ data.tar.gz: 409d8d97cd7313a17d869a7504aa596b5e8e8bb594136cb24ab658408c609ab9
5
5
  SHA512:
6
- metadata.gz: 1ac432a009738c6e6d69e3d9db07895ca67653a33f7c226194a1851978076dbde05de1da6c767e5b582f5e6e0cded2347fb2bcda858a147d4911cc7b55b06617
7
- data.tar.gz: f317a32584cc90e2b49043e4e0c5610351ba710866cd29336a43e151fb0b42061d82e8e39837ed900c6994f7c8d65214cc31845e315a84cb0fd10904c8b09b89
6
+ metadata.gz: 68e629879e301c3a92dc7c903094739a28dd019d4b1ddcd5fe8606b9c0419e3409e921483bc8b81b4c399bb375a3658a08ef1608d3da010e55f23f0d5b665a00
7
+ data.tar.gz: 8fba53a8294646354e47afd9a20afc9c48d9d3878df43e653ee09c7de98ab04604168edb19fb30d14430e641069c485d1151b371dc48ac96277ed1795f88d0c5
data/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## 3.10.0 2025-11-11
10
+
11
+ ### Added
12
+
13
+ - Support type validation and coercion for a single attribute method [#470](https://github.com/okuramasafumi/alba/pull/470)
14
+ - Thank you [@denblackstache](https://github.com/denblackstache) for requesting the feature
15
+ - Fix hash object resource methods [#475](https://github.com/okuramasafumi/alba/pull/475)
16
+ - Thank you, [@jkmcrg](https://github.com/jkmcrg)
17
+
9
18
  ## 3.9.1 2025-09-27
10
19
 
11
20
  ### Added
@@ -189,7 +198,7 @@ This change is supposed to be released as 3.8.0 with the change in 3.7.4, but I
189
198
 
190
199
  ## [2.4.1] 2023-08-02
191
200
 
192
- #### Fixed
201
+ ### Fixed
193
202
 
194
203
  - Fix the bug of resource name inference for classes whose name end with "Serializer" [No PR](https://github.com/okuramasafumi/alba/commit/1695af4351981725231fd071aaef5b2e4174fb26)
195
204
 
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/alba.svg)](https://badge.fury.io/rb/alba)
4
4
  [![CI](https://github.com/okuramasafumi/alba/actions/workflows/main.yml/badge.svg)](https://github.com/okuramasafumi/alba/actions/workflows/main.yml)
5
5
  [![codecov](https://codecov.io/gh/okuramasafumi/alba/branch/main/graph/badge.svg?token=3D3HEZ5OXT)](https://codecov.io/gh/okuramasafumi/alba)
6
- [![Maintainability](https://qlty.sh/gh/okuramasafumi/projects/alba/maintainability.svg)](https://qlty.sh/gh/okuramasafumi/projects/alba)
6
+ [![Codacy Badge](https://app.codacy.com/project/badge/Grade/acf6a96689c349ecbb806db07fa6948a)](https://app.codacy.com/gh/okuramasafumi/alba/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
7
7
  ![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/okuramasafumi/alba)
8
8
  ![GitHub](https://img.shields.io/github/license/okuramasafumi/alba)
9
9
  [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
data/lib/alba/resource.rb CHANGED
@@ -20,6 +20,9 @@ module Alba
20
20
  WITHIN_DEFAULT = Object.new.freeze
21
21
  private_constant :WITHIN_DEFAULT
22
22
 
23
+ EMPTY_HASH = {}.freeze
24
+ private_constant :EMPTY_HASH
25
+
23
26
  # `setup` method is meta-programmatically defined here for performance.
24
27
  # @api private
25
28
  def self.included(base) # rubocop:disable Metrics/MethodLength
@@ -49,7 +52,7 @@ module Alba
49
52
  # determines what associations to be serialized. If not set, it serializes all associations.
50
53
  # @param with_traits [Symbol, Array<Symbol>, nil] specified traits
51
54
  # @param select [Method] select method object used with `nested_attribute` and `trait`
52
- def initialize(object, params: {}, within: WITHIN_DEFAULT, with_traits: nil, select: nil)
55
+ def initialize(object, params: EMPTY_HASH, within: WITHIN_DEFAULT, with_traits: nil, select: nil)
53
56
  @object = object
54
57
  @params = params
55
58
  @within = within
@@ -65,7 +68,7 @@ module Alba
65
68
  # @param root_key [Symbol, nil]
66
69
  # @param meta [Hash] metadata for this serialization
67
70
  # @return [String] serialized JSON string
68
- def serialize(root_key: nil, meta: {})
71
+ def serialize(root_key: nil, meta: EMPTY_HASH)
69
72
  serialize_with(as_json(root_key: root_key, meta: meta))
70
73
  end
71
74
 
@@ -74,7 +77,7 @@ module Alba
74
77
  #
75
78
  # @see #serialize
76
79
  # @see https://github.com/rails/rails/blob/7-0-stable/actionpack/lib/action_controller/metal/renderers.rb#L156
77
- def to_json(options = {}, root_key: nil, meta: {})
80
+ def to_json(options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH)
78
81
  confusing_keys = [:only, :except]
79
82
  confusing_options = options.keys.select { |k| confusing_keys.include?(k.to_sym) }
80
83
  unless confusing_options.empty?
@@ -92,7 +95,7 @@ module Alba
92
95
  # @param root_key [Symbol, nil]
93
96
  # @param meta [Hash] metadata for this serialization
94
97
  # @return [Hash]
95
- def as_json(_options = {}, root_key: nil, meta: {})
98
+ def as_json(_options = EMPTY_HASH, root_key: nil, meta: EMPTY_HASH)
96
99
  key = root_key.nil? ? fetch_key : root_key
97
100
  key = Alba.regularize_key(key)
98
101
  if key && !key.empty?
@@ -290,7 +293,7 @@ module Alba
290
293
  when Symbol then fetch_attribute_from_object_and_resource(obj, attribute)
291
294
  when Proc then instance_exec(obj, &attribute)
292
295
  when Alba::Association then yield_if_within(attribute.name.to_sym) { |within| attribute.to_h(obj, params: params, within: within) }
293
- when TypedAttribute then attribute.value { |attr| fetch_attribute(obj, key, attr) }
296
+ when TypedAttribute then attribute.value(object: obj) { |attr| fetch_attribute(obj, key, attr) }
294
297
  when NestedAttribute then attribute.value(object: obj, params: params, within: @within, select: method(:select))
295
298
  when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: obj) { |attr| fetch_attribute(obj, key, attr) }
296
299
  # :nocov:
@@ -308,7 +311,7 @@ module Alba
308
311
  return obj.fetch(attribute) if obj.is_a?(Hash)
309
312
 
310
313
  obj.__send__(attribute)
311
- rescue NoMethodError
314
+ rescue NoMethodError, KeyError
312
315
  __send__(attribute, obj)
313
316
  end
314
317
 
@@ -320,6 +323,8 @@ module Alba
320
323
  else
321
324
  obj.__send__(attribute)
322
325
  end
326
+ rescue KeyError
327
+ __send__(attribute, obj)
323
328
  end
324
329
 
325
330
  def nil_handler
@@ -399,11 +404,11 @@ module Alba
399
404
  end
400
405
  private :assign_attributes
401
406
 
402
- def assign_attributes_with_types(attrs_with_types, if_value)
407
+ def assign_attributes_with_types(attrs_with_types, if_value, &block)
403
408
  attrs_with_types.each do |attr_name, type_and_converter|
404
409
  attr_name = attr_name.to_sym
405
410
  type, type_converter = type_and_converter
406
- typed_attr = TypedAttribute.new(name: attr_name, type: type, converter: type_converter)
411
+ typed_attr = TypedAttribute.new(name: attr_name, type: type, converter: type_converter, &block)
407
412
  attr = if_value ? ConditionalAttribute.new(body: typed_attr, condition: if_value) : typed_attr
408
413
  @_attributes[attr_name] = attr
409
414
  end
@@ -413,15 +418,21 @@ module Alba
413
418
  # Set an attribute with the given block
414
419
  #
415
420
  # @param name [String, Symbol] key name
416
- # @param options [Hash<Symbol, Proc>]
417
- # @option options [Proc] if a condition to decide if this attribute should be serialized
421
+ # @param if [Proc] condition to decide if it should serialize these attributes
418
422
  # @param block [Block] the block called during serialization
419
423
  # @raise [ArgumentError] if block is absent
420
424
  # @return [void]
421
- def attribute(name, **options, &block)
425
+ def attribute(name = nil, if: nil, **name_with_type, &block)
426
+ if_value = binding.local_variable_get(:if)
422
427
  raise ArgumentError, 'No block given in attribute method' unless block
428
+ raise ArgumentError, 'You must specify either name or name with type' if name.nil? && name_with_type.empty?
423
429
 
424
- @_attributes[name.to_sym] = options[:if] ? ConditionalAttribute.new(body: block, condition: options[:if]) : block
430
+ if name.nil?
431
+ assign_attributes_with_types(name_with_type, if_value, &block)
432
+ else # Symbol
433
+ attr = if_value ? ConditionalAttribute.new(body: block, condition: if_value) : block
434
+ @_attributes[name.to_sym] = attr
435
+ end
425
436
  end
426
437
 
427
438
  # Set association
@@ -441,7 +452,7 @@ module Alba
441
452
  # @param block [Block]
442
453
  # @return [void]
443
454
  # @see Alba::Association#initialize
444
- def association(name, condition = nil, resource: nil, serializer: nil, source: nil, key: nil, with_traits: nil, params: {}, **options, &block)
455
+ def association(name, condition = nil, resource: nil, serializer: nil, source: nil, key: nil, with_traits: nil, params: EMPTY_HASH, **options, &block)
445
456
  resource ||= serializer
446
457
  transformation = @_key_transformation_cascade ? @_transform_type : :none
447
458
  assoc = Association.new(
@@ -9,7 +9,7 @@ module Alba
9
9
  # @param name [Symbol, String]
10
10
  # @param type [Symbol, Class]
11
11
  # @param converter [Proc, true, false, nil]
12
- def initialize(name:, type:, converter:)
12
+ def initialize(name:, type:, converter:, &block)
13
13
  @name = name
14
14
  t = Alba.find_type(type)
15
15
  @type = case converter
@@ -18,11 +18,12 @@ module Alba
18
18
  else
19
19
  t.dup.tap { _1.auto_convert_with(converter) }
20
20
  end
21
+ @block = block
21
22
  end
22
23
 
23
24
  # @return [String, Integer, Boolean] type-checked or type-converted object
24
- def value
25
- v = yield(@name)
25
+ def value(object: nil)
26
+ v = @block ? @block.call(object) : yield(@name)
26
27
  result = @type.check(v)
27
28
  result ? v : @type.convert(v)
28
29
  rescue TypeError
data/lib/alba/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Alba
4
- VERSION = '3.9.1'
4
+ VERSION = '3.10.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alba
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.9.1
4
+ version: 3.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OKURA Masafumi
@@ -9,8 +9,8 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: Alba is the fastest JSON serializer for Ruby. It focuses on performance,
13
- flexibility and usability.
12
+ description: Alba is a JSON serializer for Ruby, JRuby and TruffleRuby. It focuses
13
+ on performance, flexibility and usability.
14
14
  email:
15
15
  - masafumi.o1988@gmail.com
16
16
  executables: []
@@ -59,5 +59,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
59
59
  requirements: []
60
60
  rubygems_version: 3.6.7
61
61
  specification_version: 4
62
- summary: Alba is the fastest JSON serializer for Ruby.
62
+ summary: Alba is a JSON serializer for Ruby, JRuby and TruffleRuby.
63
63
  test_files: []