alba 3.3.3 → 3.4.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 +4 -4
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile +2 -2
- data/README.md +54 -0
- data/lib/alba/resource.rb +5 -11
- data/lib/alba/version.rb +1 -1
- data/lib/alba.rb +48 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1a7b2fac43a1ae40bc0598d6f989fb7b81108d00ca929d31327113590880b2f
|
4
|
+
data.tar.gz: d6bc3c22c9178eeaf8b3b7f3d3d92bc526edd18904fa736c0c25488250f89d02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: da62c8a7d30ab7c4c39032950c9e02cef238b8662f403843351116fb86e3a3010e2780a3b5efe958697fd698e7e703a130a292129f3efad4da253cc9e84570bd
|
7
|
+
data.tar.gz: 94a580ab65397d4f61a8534bfd22999d86bdd9e6cca0ec83b15d03bd2fdbdedc220bbbaf091b20c34e58c7dfe5c7b21c9f046a78b25639dcecf59b71b95199c0
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [3.4.0] 2024-12-01
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- `Alba.serialize` now works with heterogeneous collection [#396](https://github.com/okuramasafumi/alba/pull/396)
|
14
|
+
|
9
15
|
## [3.3.3] 2024-11-09
|
10
16
|
|
11
17
|
### Fixed
|
data/Gemfile
CHANGED
@@ -11,11 +11,11 @@ gem 'ffaker', require: false # For testing
|
|
11
11
|
gem 'minitest', '~> 5.14' # For test
|
12
12
|
gem 'railties', require: false # For Rails integration testing
|
13
13
|
gem 'rake', '~> 13.0' # For test and automation
|
14
|
-
gem 'rubocop', '~> 1.
|
14
|
+
gem 'rubocop', '~> 1.69.0', require: false # For lint
|
15
15
|
gem 'rubocop-gem_dev', '>= 0.3.0', require: false # For lint
|
16
16
|
gem 'rubocop-md', '~> 1.0', require: false # For lint
|
17
17
|
gem 'rubocop-minitest', '~> 0.36.0', require: false # For lint
|
18
|
-
gem 'rubocop-performance', '~> 1.
|
18
|
+
gem 'rubocop-performance', '~> 1.23.0', require: false # For lint
|
19
19
|
gem 'rubocop-rake', '~> 0.6.0', require: false # For lint
|
20
20
|
gem 'simplecov', '~> 0.22.0', require: false # For test coverage
|
21
21
|
gem 'simplecov-cobertura', require: false # For test coverage
|
data/README.md
CHANGED
@@ -730,6 +730,60 @@ end
|
|
730
730
|
# => JSON containing "foo" and "bar" as root keys
|
731
731
|
```
|
732
732
|
|
733
|
+
#### Inline definition with heterogeneous collection
|
734
|
+
|
735
|
+
Alba allows to serialize a heterogeneous collection with `Alba.serialize`.
|
736
|
+
|
737
|
+
```ruby
|
738
|
+
Foo = Data.define(:id, :name)
|
739
|
+
Bar = Data.define(:id, :address)
|
740
|
+
|
741
|
+
class FooResource
|
742
|
+
include Alba::Resource
|
743
|
+
|
744
|
+
attributes :id, :name
|
745
|
+
end
|
746
|
+
|
747
|
+
class BarResource
|
748
|
+
include Alba::Resource
|
749
|
+
|
750
|
+
attributes :id, :address
|
751
|
+
end
|
752
|
+
|
753
|
+
class CustomFooResource
|
754
|
+
include Alba::Resource
|
755
|
+
|
756
|
+
attributes :id
|
757
|
+
end
|
758
|
+
|
759
|
+
foo1 = Foo.new(1, 'foo1')
|
760
|
+
foo2 = Foo.new(2, 'foo2')
|
761
|
+
bar1 = Bar.new(1, 'bar1')
|
762
|
+
bar2 = Bar.new(2, 'bar2')
|
763
|
+
|
764
|
+
# This works only when inflector is set
|
765
|
+
Alba.serialize([foo1, bar1, foo2, bar2], with: :inference)
|
766
|
+
# => '[{"id":1,"name":"foo1"},{"id":1,"address":"bar1"},{"id":2,"name":"foo2"},{"id":2,"address":"bar2"}]'
|
767
|
+
|
768
|
+
Alba.serialize(
|
769
|
+
[foo1, bar1, foo2, bar2],
|
770
|
+
# `with` option takes a lambda to return resource class
|
771
|
+
with: lambda do |obj|
|
772
|
+
case obj
|
773
|
+
when Foo
|
774
|
+
CustomFooResource
|
775
|
+
when Bar
|
776
|
+
BarResource
|
777
|
+
else
|
778
|
+
raise # Impossible in this case
|
779
|
+
end
|
780
|
+
end
|
781
|
+
)
|
782
|
+
# => '[{"id":1},{"id":1,"address":"bar1"},{"id":2},{"id":2,"address":"bar2"}]'
|
783
|
+
# Note `CustomFooResource` is used here
|
784
|
+
|
785
|
+
```
|
786
|
+
|
733
787
|
### Serializable Hash
|
734
788
|
|
735
789
|
Instead of serializing to JSON, you can also output a Hash by calling `serializable_hash` or the `to_h` alias. Note also that the `serialize` method is aliased as `to_json`.
|
data/lib/alba/resource.rb
CHANGED
@@ -56,7 +56,7 @@ module Alba
|
|
56
56
|
# Serialize object into JSON string
|
57
57
|
#
|
58
58
|
# @param root_key [Symbol, nil, true]
|
59
|
-
# @param meta [Hash] metadata for this
|
59
|
+
# @param meta [Hash] metadata for this serialization
|
60
60
|
# @return [String] serialized JSON string
|
61
61
|
def serialize(root_key: nil, meta: {})
|
62
62
|
serialize_with(as_json(root_key: root_key, meta: meta))
|
@@ -78,11 +78,11 @@ module Alba
|
|
78
78
|
serialize(root_key: root_key, meta: meta)
|
79
79
|
end
|
80
80
|
|
81
|
-
# Returns a Hash
|
81
|
+
# Returns a Hash corresponding {#serialize}
|
82
82
|
#
|
83
83
|
# @param _options [Hash] dummy parameter for Rails compatibility
|
84
84
|
# @param root_key [Symbol, nil, true]
|
85
|
-
# @param meta [Hash] metadata for this
|
85
|
+
# @param meta [Hash] metadata for this serialization
|
86
86
|
# @return [Hash]
|
87
87
|
def as_json(_options = {}, root_key: nil, meta: {})
|
88
88
|
key = root_key.nil? ? fetch_key : root_key
|
@@ -99,7 +99,7 @@ module Alba
|
|
99
99
|
#
|
100
100
|
# @return [Hash]
|
101
101
|
def serializable_hash
|
102
|
-
collection? ? serializable_hash_for_collection : converter.call(@object)
|
102
|
+
Alba.collection?(@object) ? serializable_hash_for_collection : converter.call(@object)
|
103
103
|
end
|
104
104
|
alias to_h serializable_hash
|
105
105
|
|
@@ -143,7 +143,7 @@ module Alba
|
|
143
143
|
|
144
144
|
# @return [String]
|
145
145
|
def fetch_key
|
146
|
-
k = collection? ? _key_for_collection : _key
|
146
|
+
k = Alba.collection?(@object) ? _key_for_collection : _key
|
147
147
|
transforming_root_key? ? transform_key(k) : k
|
148
148
|
end
|
149
149
|
|
@@ -292,12 +292,6 @@ module Alba
|
|
292
292
|
raise Alba::Error, "Unknown type for within option: #{@within.class}"
|
293
293
|
end
|
294
294
|
end
|
295
|
-
|
296
|
-
# Detect if object is a collection or not.
|
297
|
-
# When object is a Struct, it's Enumerable but not a collection
|
298
|
-
def collection?
|
299
|
-
@object.is_a?(Enumerable) && !@object.is_a?(Struct)
|
300
|
-
end
|
301
295
|
end
|
302
296
|
|
303
297
|
# Class methods
|
data/lib/alba/version.rb
CHANGED
data/lib/alba.rb
CHANGED
@@ -42,25 +42,44 @@ module Alba
|
|
42
42
|
# Serialize the object with inline definitions
|
43
43
|
#
|
44
44
|
# @param object [Object] the object to be serialized
|
45
|
+
# @param with [:inference, Proc, Class<Alba::Resource>] determines how to get resource class for each object
|
45
46
|
# @param root_key [Symbol, nil, true]
|
46
47
|
# @param block [Block] resource block
|
47
48
|
# @return [String] serialized JSON string
|
48
49
|
# @raise [ArgumentError] if block is absent or `with` argument's type is wrong
|
49
|
-
def serialize(object = nil, root_key: nil, &block)
|
50
|
-
|
51
|
-
|
50
|
+
def serialize(object = nil, with: :inference, root_key: nil, &block)
|
51
|
+
if collection?(object)
|
52
|
+
h = hashify_collection(object, with, &block)
|
53
|
+
Alba.encoder.call(h)
|
54
|
+
else
|
55
|
+
resource = resource_with(object, &block)
|
56
|
+
resource.serialize(root_key: root_key)
|
57
|
+
end
|
52
58
|
end
|
53
59
|
|
54
60
|
# Hashify the object with inline definitions
|
55
61
|
#
|
56
62
|
# @param object [Object] the object to be serialized
|
63
|
+
# @param with [:inference, Proc, Class<Alba::Resource>] determines how to get resource class for each object
|
57
64
|
# @param root_key [Symbol, nil, true]
|
58
65
|
# @param block [Block] resource block
|
59
66
|
# @return [String] serialized JSON string
|
60
67
|
# @raise [ArgumentError] if block is absent or `with` argument's type is wrong
|
61
|
-
def hashify(object = nil, root_key: nil, &block)
|
62
|
-
|
63
|
-
|
68
|
+
def hashify(object = nil, with: :inference, root_key: nil, &block)
|
69
|
+
if collection?(object)
|
70
|
+
hashify_collection(object, with, &block)
|
71
|
+
else
|
72
|
+
resource = resource_with(object, &block)
|
73
|
+
resource.as_json(root_key: root_key)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Detect if object is a collection or not.
|
78
|
+
# When object is a Struct, it's Enumerable but not a collection
|
79
|
+
#
|
80
|
+
# @api private
|
81
|
+
def collection?(object)
|
82
|
+
object.is_a?(Enumerable) && !object.is_a?(Struct)
|
64
83
|
end
|
65
84
|
|
66
85
|
# Enable inference for key and resource name
|
@@ -192,7 +211,11 @@ module Alba
|
|
192
211
|
register_default_types
|
193
212
|
end
|
194
213
|
|
195
|
-
#
|
214
|
+
# Get a resource object from arguments
|
215
|
+
# If block is given, it creates a resource class with the block
|
216
|
+
# Otherwise, it infers resource class from the object's class name
|
217
|
+
#
|
218
|
+
# @ param object [Object] the object whose class name is used for inferring resource class
|
196
219
|
def resource_with(object, &block)
|
197
220
|
klass = block ? resource_class(&block) : infer_resource_class(object.class.name)
|
198
221
|
|
@@ -253,6 +276,24 @@ module Alba
|
|
253
276
|
end
|
254
277
|
end
|
255
278
|
|
279
|
+
def hashify_collection(collection, with, &block) # rubocop:disable Metrics/MethodLength
|
280
|
+
collection.map do |obj|
|
281
|
+
resource = if block
|
282
|
+
resource_class(&block)
|
283
|
+
else
|
284
|
+
case with
|
285
|
+
when Class then with
|
286
|
+
when :inference then infer_resource_class(obj.class.name)
|
287
|
+
when Proc then with.call(obj)
|
288
|
+
else raise ArgumentError, '`with` argument must be either :inference, Proc or Class'
|
289
|
+
end
|
290
|
+
end
|
291
|
+
raise Alba::Error if resource.nil?
|
292
|
+
|
293
|
+
resource.new(obj).to_h
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
256
297
|
def validate_inflector(inflector)
|
257
298
|
unless %i[camelize camelize_lower dasherize classify].all? { |m| inflector.respond_to?(m) }
|
258
299
|
raise Alba::Error, "Given inflector, #{inflector.inspect} is not valid. It must implement `camelize`, `camelize_lower`, `dasherize` and `classify`."
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OKURA Masafumi
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2024-
|
10
|
+
date: 2024-12-01 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: ostruct
|