alba 3.10.0 → 4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +33 -20
- data/lib/alba/association.rb +1 -9
- data/lib/alba/nested_attribute.rb +7 -5
- data/lib/alba/railtie.rb +4 -4
- data/lib/alba/resource.rb +10 -59
- data/lib/alba/version.rb +1 -1
- data/lib/alba.rb +33 -45
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0ec3b28fdf4ed9303e346f6dca7771480d8b9bba19dea65374b41a526e895c10
|
|
4
|
+
data.tar.gz: 1ca8398f44a505fbdfc7bc5df7b743de07e4dc6bcd7580bdff3dec0732278474
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0dd664193cc78874ac9e5e2630eaf201d172ce170137084041b65e8e683d95f435c4609df296b2f8b47b588219576e9e743473d83c0f7854a9e6ec6a25c0cce0
|
|
7
|
+
data.tar.gz: 3fc3dc98d059878f5f97e40c81999f0990ee96bb82848acc63cc5c0b49c4240bed2c1b17a077ac46d16754c1e603c6839617e1afa1e1185371885bdc9589955b
|
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## 4.0.0 2026-08-28
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Call #nil? on attribute values only when a nil handler is set [#546](https://github.com/okuramasafumi/alba/pull/546)
|
|
14
|
+
|
|
15
|
+
### Removed
|
|
16
|
+
|
|
17
|
+
- Remove the deprecated inference methods `Alba.enable_inference!`, `Alba.disable_inference!`, and `Alba.inferring`; use `Alba.inflector` and `Alba.inflector=` instead
|
|
18
|
+
- Remove the deprecated `Alba.resource_with`; use `Alba.resource_for` instead
|
|
19
|
+
- Remove deprecated support for overriding `Alba::Resource#attributes`; override `Alba::Resource#select` to filter attributes instead
|
|
20
|
+
- Remove the deprecated `converter` and `collection_converter` serialization hooks
|
|
21
|
+
- Remove the deprecated `select` keyword argument from `Alba::Resource#initialize`; the `Alba::Resource#select` filtering method remains available
|
|
22
|
+
|
|
23
|
+
## 3.11.0 2026-07-25
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- Rails: `serialize` and `render_serialized_json` now takes `params` [#509](https://github.com/okuramasafumi/alba/pull/509)
|
|
28
|
+
- Add `Alba.non_collection_types` for declaring Enumerable classes that should not be treated as collections [#532](https://github.com/okuramasafumi/alba/pull/532)
|
|
29
|
+
- Add default superclass configuration [#547](https://github.com/okuramasafumi/alba/pull/547)
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Trait redefining base-level attribute causes wrong result with multiple traits [#498](https://github.com/okuramasafumi/alba/issues/498) and [#502](https://github.com/okuramasafumi/alba/pull/502)
|
|
34
|
+
- Thank you for reporting this issue, @yukihiro-numata
|
|
35
|
+
- Pass params to resource in serialize when with is given [#524](https://github.com/okuramasafumi/alba/pull/524)
|
|
36
|
+
- Thank you, @JohnnyKei
|
|
37
|
+
- `Alba.serialize(single, with: SomeResource)` crash
|
|
38
|
+
- helpers are now available in NestedAttribute [#503](https://github.com/okuramasafumi/alba/pull/503)
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- More strict types
|
|
43
|
+
|
|
9
44
|
## 3.10.0 2025-11-11
|
|
10
45
|
|
|
11
46
|
### Added
|
data/README.md
CHANGED
|
@@ -12,16 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
Alba is a JSON serializer for Ruby, JRuby, and TruffleRuby.
|
|
14
14
|
|
|
15
|
-
## IMPORTANT NOTICE
|
|
16
|
-
|
|
17
|
-
Both version `3.0.0` and `2.4.2` contain important bug fix.
|
|
18
|
-
~~However, version `3.0.0` has some bugs (see https://github.com/okuramasafumi/alba/issues/342).
|
|
19
|
-
Until they get fixed, it's highly recommended to upgrade to version `2.4.2`.
|
|
20
|
-
Dependabot and similar tools might create an automated Pull Request to upgrade to `3.0.0`, so it might be required to upgrade to `2.4.2` manually.~~
|
|
21
|
-
Version `3.0.1` has been released so Ruby 3 users should upgrade to `3.0.1`.
|
|
22
|
-
For Ruby 2 users, it's highly recommended to upgrade to `2.4.2`.
|
|
23
|
-
Sorry for the inconvenience.
|
|
24
|
-
|
|
25
15
|
## TL;DR
|
|
26
16
|
|
|
27
17
|
Alba allows you to do something like below.
|
|
@@ -56,6 +46,12 @@ UserResource.new(user).serialize
|
|
|
56
46
|
|
|
57
47
|
Seems useful? Continue reading!
|
|
58
48
|
|
|
49
|
+
Pro tip: You can find more examples in separate Ruby files under "examples" directory.
|
|
50
|
+
|
|
51
|
+
### Coming from ActiveModelSerializers(AMS)?
|
|
52
|
+
|
|
53
|
+
If you are using ActiveModelSerializers and interested in Alba, we have an automatic converter! [alba_migration](https://github.com/ShoheiMitani/alba_migration) gem from [ShoheiMitani](https://github.com/ShoheiMitani) "provides a command-line tool to convert AMS serializer classes to Alba resource classes, making your migration process easier and less error-prone."
|
|
54
|
+
|
|
59
55
|
## Discussions
|
|
60
56
|
|
|
61
57
|
Alba uses [GitHub Discussions](https://github.com/okuramasafumi/alba/discussions) to openly discuss the project.
|
|
@@ -100,6 +96,7 @@ While Alba's core is simple, it provides additional features when you need them.
|
|
|
100
96
|
- Well tested, the test coverage is 99%
|
|
101
97
|
- Well maintained, getting frequent update and new releases (see [version history](https://rubygems.org/gems/alba/versions))
|
|
102
98
|
|
|
99
|
+
|
|
103
100
|
## Comparison with other serializers
|
|
104
101
|
|
|
105
102
|
Alba aims to provide a well-balanced combination of simplicity, performance, and features. Here's how it compares to other popular Ruby JSON serializers:
|
|
@@ -138,7 +135,7 @@ Or install it yourself as:
|
|
|
138
135
|
|
|
139
136
|
## Supported Ruby versions
|
|
140
137
|
|
|
141
|
-
Alba
|
|
138
|
+
Alba works with CRuby 3.0 and higher and latest JRuby and TruffleRuby. However, Ruby 3.0 is not actively tested, so use it at your own risk.
|
|
142
139
|
|
|
143
140
|
## Documentation
|
|
144
141
|
|
|
@@ -228,6 +225,20 @@ else
|
|
|
228
225
|
end
|
|
229
226
|
```
|
|
230
227
|
|
|
228
|
+
#### Default superclass configuration
|
|
229
|
+
|
|
230
|
+
You can set the default superclass for resource classes created for Nested Attributes and Traits.
|
|
231
|
+
|
|
232
|
+
```ruby
|
|
233
|
+
Alba.default_superclass = MyBaseSerializer
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Note that in some environments like Rails applications, the class object is not loaded in the initializer phase. You can also set `String`.
|
|
237
|
+
|
|
238
|
+
```ruby
|
|
239
|
+
Alba.default_superclass = 'MyBaseSerializer'
|
|
240
|
+
```
|
|
241
|
+
|
|
231
242
|
### Naming
|
|
232
243
|
|
|
233
244
|
Alba tries to infer resource name from class name like the following.
|
|
@@ -349,7 +360,7 @@ end
|
|
|
349
360
|
class FooResource
|
|
350
361
|
include Alba::Resource
|
|
351
362
|
|
|
352
|
-
attributes :
|
|
363
|
+
attributes :format
|
|
353
364
|
|
|
354
365
|
# Here, `format` method is available
|
|
355
366
|
end
|
|
@@ -1921,16 +1932,18 @@ Don't forget calling `super` in this way.
|
|
|
1921
1932
|
|
|
1922
1933
|
### Treating specific classes as non-collection
|
|
1923
1934
|
|
|
1924
|
-
Sometimes we need to serialize an object that's `Enumerable` but not a collection. By default, Alba treats `Hash`, `Range` and `Struct` as non-collection
|
|
1935
|
+
Sometimes we need to serialize an object that's `Enumerable` but not a collection. By default, Alba treats `Hash`, `Range` and `Struct` as non-collection objects. You can add additional classes to this list via `Alba.non_collection_types`:
|
|
1925
1936
|
|
|
1926
1937
|
```ruby
|
|
1927
|
-
Alba.
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1938
|
+
Alba.non_collection_types << Stripe::StripeObject
|
|
1939
|
+
Alba.non_collection_types << MyEnumerableEntity
|
|
1940
|
+
```
|
|
1941
|
+
|
|
1942
|
+
You can inspect the current list of excluded types (including the defaults) at any time:
|
|
1943
|
+
|
|
1944
|
+
```ruby
|
|
1945
|
+
Alba.non_collection_types
|
|
1946
|
+
# => [Struct, Range, Hash, Stripe::StripeObject, MyEnumerableEntity]
|
|
1934
1947
|
```
|
|
1935
1948
|
|
|
1936
1949
|
### Adding indexes to `many` association
|
data/lib/alba/association.rb
CHANGED
|
@@ -101,7 +101,7 @@ module Alba
|
|
|
101
101
|
|
|
102
102
|
def assign_resource(nesting, key_transformation, block, helper)
|
|
103
103
|
@resource = if block
|
|
104
|
-
|
|
104
|
+
Alba.resource_class(helper: helper, key_transformation: key_transformation, &block)
|
|
105
105
|
elsif Alba.inflector
|
|
106
106
|
Alba.infer_resource_class(@name, nesting: nesting)
|
|
107
107
|
else
|
|
@@ -109,14 +109,6 @@ module Alba
|
|
|
109
109
|
end
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
def charged_resource_class(helper, key_transformation, block)
|
|
113
|
-
klass = Alba.resource_class
|
|
114
|
-
klass.helper(helper) if helper
|
|
115
|
-
klass.transform_keys(key_transformation)
|
|
116
|
-
klass.class_eval(&block)
|
|
117
|
-
klass
|
|
118
|
-
end
|
|
119
|
-
|
|
120
112
|
def to_h_with_each_resource(object, within, params)
|
|
121
113
|
object.map do |item|
|
|
122
114
|
@resource.call(item).new(item, within: within, params: params, with_traits: @with_traits).to_h
|
|
@@ -7,9 +7,11 @@ module Alba
|
|
|
7
7
|
# Setter for key_transformation, used when it's changed after class definition
|
|
8
8
|
attr_writer :key_transformation
|
|
9
9
|
|
|
10
|
+
# @param klass [Class<Alba::Resource>] the parent for this nested attribute
|
|
10
11
|
# @param key_transformation [Symbol] determines how to transform keys
|
|
11
12
|
# @param block [Proc] class body
|
|
12
|
-
def initialize(key_transformation: :none, &block)
|
|
13
|
+
def initialize(klass:, key_transformation: :none, &block)
|
|
14
|
+
@klass = klass
|
|
13
15
|
@key_transformation = key_transformation
|
|
14
16
|
@block = block
|
|
15
17
|
end
|
|
@@ -17,13 +19,13 @@ module Alba
|
|
|
17
19
|
# @param object [Object] the object being serialized
|
|
18
20
|
# @param params [Hash] params Hash inherited from Resource
|
|
19
21
|
# @param within [Object, nil, false, true] determines what associations to be serialized. If not set, it serializes all associations.
|
|
20
|
-
# @param select [Method] select method object from its origin
|
|
21
22
|
# @return [Hash] hash serialized from running the class body in the object
|
|
22
|
-
def value(object:, params:, within
|
|
23
|
-
resource_class =
|
|
23
|
+
def value(object:, params:, within:)
|
|
24
|
+
resource_class = Class.new(@klass)
|
|
25
|
+
resource_class.instance_variable_set(:@_attributes, {}) # reset
|
|
24
26
|
resource_class.transform_keys(@key_transformation)
|
|
25
27
|
resource_class.class_eval(&@block)
|
|
26
|
-
resource_class.new(object, params: params, within: within
|
|
28
|
+
resource_class.new(object, params: params, within: within).serializable_hash
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
end
|
data/lib/alba/railtie.rb
CHANGED
|
@@ -7,13 +7,13 @@ module Alba
|
|
|
7
7
|
Alba.inflector = :active_support
|
|
8
8
|
|
|
9
9
|
ActiveSupport.on_load(:action_controller) do
|
|
10
|
-
define_method(:serialize) do |obj, with: nil, root_key: nil, meta: {}, &block|
|
|
11
|
-
resource = with.nil? ? Alba.resource_for(obj, &block) : with.new(obj)
|
|
10
|
+
define_method(:serialize) do |obj, params: {}, with: nil, root_key: nil, meta: {}, &block|
|
|
11
|
+
resource = with.nil? ? Alba.resource_for(obj, params: params, &block) : with.new(obj, params: params)
|
|
12
12
|
resource.to_json(root_key: root_key, meta: meta)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
define_method(:render_serialized_json) do |obj, with: nil, root_key: nil, meta: {}, &block|
|
|
16
|
-
json = with.nil? ? Alba.resource_for(obj, &block) : with.new(obj)
|
|
15
|
+
define_method(:render_serialized_json) do |obj, params: {}, with: nil, root_key: nil, meta: {}, &block|
|
|
16
|
+
json = with.nil? ? Alba.resource_for(obj, params: params, &block) : with.new(obj, params: params)
|
|
17
17
|
render json: json.to_json(root_key: root_key, meta: meta)
|
|
18
18
|
end
|
|
19
19
|
end
|
data/lib/alba/resource.rb
CHANGED
|
@@ -51,15 +51,11 @@ module Alba
|
|
|
51
51
|
# @param within [Alba::WITHIN_DEFAULT, Hash, Array, nil, false, true]
|
|
52
52
|
# determines what associations to be serialized. If not set, it serializes all associations.
|
|
53
53
|
# @param with_traits [Symbol, Array<Symbol>, nil] specified traits
|
|
54
|
-
|
|
55
|
-
def initialize(object, params: EMPTY_HASH, within: WITHIN_DEFAULT, with_traits: nil, select: nil)
|
|
54
|
+
def initialize(object, params: EMPTY_HASH, within: WITHIN_DEFAULT, with_traits: nil)
|
|
56
55
|
@object = object
|
|
57
56
|
@params = params
|
|
58
57
|
@within = within
|
|
59
58
|
@with_traits = with_traits
|
|
60
|
-
# select override to share the same method with `trait` and `nested_attribute`
|
|
61
|
-
# Trait and NestedAttribute generates anonymous class so it checks if it's anonymous class to prevent accidental overriding
|
|
62
|
-
self.class.define_method(:select, &select) if select && self.class.name.nil?
|
|
63
59
|
_setup
|
|
64
60
|
end
|
|
65
61
|
|
|
@@ -122,16 +118,13 @@ module Alba
|
|
|
122
118
|
Array(@with_traits).each_with_object({}) do |trait, hash|
|
|
123
119
|
body = @_traits.fetch(trait) { raise Alba::Error, "Trait not found: #{trait}" }
|
|
124
120
|
resource_class = Class.new(self.class)
|
|
121
|
+
resource_class.instance_variable_set(:@_attributes, {})
|
|
125
122
|
resource_class.class_eval(&body)
|
|
126
123
|
resource_class.transform_keys(@_transform_type) unless @_transform_type == :none
|
|
127
|
-
hash.merge!(resource_class.new(obj, params: params, within: @within
|
|
124
|
+
hash.merge!(resource_class.new(obj, params: params, within: @within).serializable_hash)
|
|
128
125
|
end
|
|
129
126
|
end
|
|
130
127
|
|
|
131
|
-
def deprecated_serializable_hash
|
|
132
|
-
Alba.collection?(@object) ? serializable_hash_for_collection : converter.call(@object)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
128
|
def serialize_with(hash)
|
|
136
129
|
serialized_json = encode(hash)
|
|
137
130
|
return serialized_json unless @_layout
|
|
@@ -168,18 +161,6 @@ module Alba
|
|
|
168
161
|
end
|
|
169
162
|
end
|
|
170
163
|
|
|
171
|
-
def deprecated_serializable_hash_for_collection
|
|
172
|
-
if @_collection_key
|
|
173
|
-
@object.to_h do |item|
|
|
174
|
-
k = item.public_send(@_collection_key)
|
|
175
|
-
key = Alba.regularize_key(k)
|
|
176
|
-
[key, converter.call(item)]
|
|
177
|
-
end
|
|
178
|
-
else
|
|
179
|
-
@object.each_with_object([], &collection_converter)
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
164
|
# @return [String]
|
|
184
165
|
def fetch_key
|
|
185
166
|
k = Alba.collection?(@object) ? _key_for_collection : _key
|
|
@@ -211,23 +192,8 @@ module Alba
|
|
|
211
192
|
@_transforming_root_key
|
|
212
193
|
end
|
|
213
194
|
|
|
214
|
-
def converter
|
|
215
|
-
lambda do |obj|
|
|
216
|
-
attributes_to_hash(obj, {})
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def collection_converter
|
|
221
|
-
lambda do |obj, a|
|
|
222
|
-
a << {}
|
|
223
|
-
h = a.last
|
|
224
|
-
attributes_to_hash(obj, h)
|
|
225
|
-
a
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
195
|
def attributes_to_hash(obj, hash)
|
|
230
|
-
|
|
196
|
+
@_attributes.each do |key, attribute|
|
|
231
197
|
set_key_and_attribute_body_from(obj, key, attribute, hash)
|
|
232
198
|
rescue ::Alba::Error, FrozenError, TypeError
|
|
233
199
|
raise
|
|
@@ -237,14 +203,6 @@ module Alba
|
|
|
237
203
|
@with_traits.nil? ? hash : hash.merge!(hash_from_traits(obj))
|
|
238
204
|
end
|
|
239
205
|
|
|
240
|
-
# This is default behavior for getting attributes for serialization
|
|
241
|
-
# Override this method to filter certain attributes
|
|
242
|
-
#
|
|
243
|
-
# @deprecated in favor of `select`
|
|
244
|
-
def attributes
|
|
245
|
-
@_attributes
|
|
246
|
-
end
|
|
247
|
-
|
|
248
206
|
# Default implementation for selecting attributes
|
|
249
207
|
# Override this method to filter attributes based on key and value
|
|
250
208
|
def select(_key, _value, _attribute)
|
|
@@ -294,13 +252,13 @@ module Alba
|
|
|
294
252
|
when Proc then instance_exec(obj, &attribute)
|
|
295
253
|
when Alba::Association then yield_if_within(attribute.name.to_sym) { |within| attribute.to_h(obj, params: params, within: within) }
|
|
296
254
|
when TypedAttribute then attribute.value(object: obj) { |attr| fetch_attribute(obj, key, attr) }
|
|
297
|
-
when NestedAttribute then attribute.value(object: obj, params: params, within: @within
|
|
255
|
+
when NestedAttribute then attribute.value(object: obj, params: params, within: @within)
|
|
298
256
|
when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: obj) { |attr| fetch_attribute(obj, key, attr) }
|
|
299
257
|
# :nocov:
|
|
300
258
|
else raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
|
|
301
259
|
# :nocov:
|
|
302
260
|
end
|
|
303
|
-
value.nil?
|
|
261
|
+
nil_handler && value.nil? ? instance_exec(obj, key, attribute, &nil_handler) : value
|
|
304
262
|
end
|
|
305
263
|
|
|
306
264
|
def fetch_attribute_from_object_and_resource(obj, attribute)
|
|
@@ -354,16 +312,8 @@ module Alba
|
|
|
354
312
|
attr_reader(*INTERNAL_VARIABLES.keys)
|
|
355
313
|
|
|
356
314
|
# This `method_added` is used for defining "resource methods"
|
|
357
|
-
def method_added(method_name)
|
|
315
|
+
def method_added(method_name)
|
|
358
316
|
case method_name
|
|
359
|
-
when :collection_converter, :converter
|
|
360
|
-
warn "Defining ##{method_name} methods is deprecated", category: :deprecated, uplevel: 1
|
|
361
|
-
alias_method :serializable_hash_for_collection, :deprecated_serializable_hash_for_collection
|
|
362
|
-
private(:serializable_hash_for_collection)
|
|
363
|
-
alias_method :serializable_hash, :deprecated_serializable_hash
|
|
364
|
-
alias_method :to_h, :deprecated_serializable_hash
|
|
365
|
-
when :attributes
|
|
366
|
-
warn 'Overriding `attributes` is deprecated, use `select` instead.', category: :deprecated, uplevel: 1
|
|
367
317
|
when :select
|
|
368
318
|
@_select_arity = instance_method(:select).arity
|
|
369
319
|
when :_setup # noop
|
|
@@ -488,7 +438,7 @@ module Alba
|
|
|
488
438
|
raise ArgumentError, 'No block given in attribute method' unless block
|
|
489
439
|
|
|
490
440
|
key_transformation = @_key_transformation_cascade ? @_transform_type : :none
|
|
491
|
-
attribute = NestedAttribute.new(key_transformation: key_transformation, &block)
|
|
441
|
+
attribute = NestedAttribute.new(klass: self, key_transformation: key_transformation, &block)
|
|
492
442
|
@_attributes[name.to_sym] = options[:if] ? ConditionalAttribute.new(body: attribute, condition: options[:if]) : attribute
|
|
493
443
|
end
|
|
494
444
|
alias nested nested_attribute
|
|
@@ -633,7 +583,8 @@ module Alba
|
|
|
633
583
|
# @return [void]
|
|
634
584
|
def helper(mod = @_helper || Module.new, &block)
|
|
635
585
|
mod.module_eval(&block) if block
|
|
636
|
-
|
|
586
|
+
include(mod)
|
|
587
|
+
extend(mod)
|
|
637
588
|
|
|
638
589
|
@_helper = mod
|
|
639
590
|
end
|
data/lib/alba/version.rb
CHANGED
data/lib/alba.rb
CHANGED
|
@@ -16,6 +16,16 @@ module Alba
|
|
|
16
16
|
# Getter for inflector, a module responsible for inflecting strings
|
|
17
17
|
attr_reader :inflector
|
|
18
18
|
|
|
19
|
+
# @return [Array<Class>] classes that include Enumerable but should not be treated as collections
|
|
20
|
+
attr_reader :non_collection_types
|
|
21
|
+
|
|
22
|
+
# Set the default superclass for resource classes created with {.resource_class}
|
|
23
|
+
#
|
|
24
|
+
# @param value [Class, String, Symbol] the default superclass
|
|
25
|
+
# @example
|
|
26
|
+
# Alba.default_superclass = '::MyApp::BaseResource'
|
|
27
|
+
attr_writer :default_superclass
|
|
28
|
+
|
|
19
29
|
# Set the backend, which actually serializes object into JSON
|
|
20
30
|
#
|
|
21
31
|
# @param backend [#to_sym, nil] the name of the backend
|
|
@@ -54,7 +64,7 @@ module Alba
|
|
|
54
64
|
h = hashify_collection(object, with, root_key, &block)
|
|
55
65
|
Alba.encoder.call(h)
|
|
56
66
|
else
|
|
57
|
-
resource = resource_for(object, &block)
|
|
67
|
+
resource = resource_for(object, with: with, &block)
|
|
58
68
|
resource.serialize(root_key: root_key)
|
|
59
69
|
end
|
|
60
70
|
end
|
|
@@ -73,45 +83,18 @@ module Alba
|
|
|
73
83
|
if collection?(object)
|
|
74
84
|
hashify_collection(object, with, root_key, &block)
|
|
75
85
|
else
|
|
76
|
-
resource = resource_for(object, &block)
|
|
86
|
+
resource = resource_for(object, with: with, &block)
|
|
77
87
|
resource.as_json(root_key: root_key)
|
|
78
88
|
end
|
|
79
89
|
end
|
|
80
90
|
|
|
81
91
|
# Detect if object is a collection or not.
|
|
82
|
-
#
|
|
92
|
+
# Types in {.non_collection_types} (default: Struct, Range, Hash) are
|
|
93
|
+
# considered non-collection even if they include Enumerable.
|
|
83
94
|
#
|
|
84
95
|
# @api private
|
|
85
96
|
def collection?(object)
|
|
86
|
-
object.is_a?(Enumerable) &&
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Enable inference for key and resource name
|
|
90
|
-
#
|
|
91
|
-
# @param with [Symbol, Class, Module] inflector
|
|
92
|
-
# When it's a Symbol, it sets inflector with given name
|
|
93
|
-
# When it's a Class or a Module, it sets given object to inflector
|
|
94
|
-
# @deprecated Use {.inflector=} instead
|
|
95
|
-
def enable_inference!(with:)
|
|
96
|
-
Alba::Deprecation.warn('Alba.enable_inference! is deprecated. Use `Alba.inflector=` instead.')
|
|
97
|
-
@inflector = inflector_from(with)
|
|
98
|
-
@inferring = true
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
# Disable inference for key and resource name
|
|
102
|
-
#
|
|
103
|
-
# @deprecated Use {.inflector=} instead
|
|
104
|
-
def disable_inference!
|
|
105
|
-
Alba::Deprecation.warn('Alba.disable_inference! is deprecated. Use `Alba.inflector = nil` instead.')
|
|
106
|
-
@inferring = false
|
|
107
|
-
@inflector = nil
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# @deprecated Use {.inflector} instead
|
|
111
|
-
# @return [Boolean] whether inference is enabled or not
|
|
112
|
-
def inferring
|
|
113
|
-
Alba::Deprecation.warn('Alba.inferring is deprecated. Use `Alba.inflector` instead.')
|
|
114
|
-
@inferring
|
|
97
|
+
object.is_a?(Enumerable) && @non_collection_types.none? { |type| object.is_a?(type) }
|
|
115
98
|
end
|
|
116
99
|
|
|
117
100
|
# Set an inflector
|
|
@@ -124,11 +107,15 @@ module Alba
|
|
|
124
107
|
reset_transform_keys
|
|
125
108
|
end
|
|
126
109
|
|
|
110
|
+
# @param helper [Module] helper module to include
|
|
111
|
+
# @param key_transformation [Symbol] key transformation type
|
|
127
112
|
# @param block [Block] resource body
|
|
128
113
|
# @return [Class<Alba::Resource>] resource class
|
|
129
|
-
def resource_class(&block)
|
|
130
|
-
klass = Class.new
|
|
114
|
+
def resource_class(helper: nil, key_transformation: :none, &block)
|
|
115
|
+
klass = Class.new(resolved_default_superclass)
|
|
131
116
|
klass.include(Alba::Resource)
|
|
117
|
+
klass.helper(helper) if helper
|
|
118
|
+
klass.transform_keys(key_transformation)
|
|
132
119
|
klass.class_eval(&block) if block
|
|
133
120
|
klass
|
|
134
121
|
end
|
|
@@ -219,21 +206,18 @@ module Alba
|
|
|
219
206
|
@_on_error = :raise
|
|
220
207
|
@_on_nil = nil
|
|
221
208
|
@types = {}
|
|
209
|
+
@non_collection_types = [Struct, Range, Hash]
|
|
210
|
+
@default_superclass = ::Object
|
|
222
211
|
reset_transform_keys
|
|
223
212
|
register_default_types
|
|
224
213
|
end
|
|
225
214
|
|
|
226
|
-
# @deprecated Use resource_for instead
|
|
227
|
-
def resource_with(object, with: :inference, &block)
|
|
228
|
-
Kernel.warn('Alba.resource_with is deprecated. Use `Alba.resource_for` instead.')
|
|
229
|
-
_resource_for(object, with: with, &block)
|
|
230
|
-
end
|
|
231
|
-
|
|
232
215
|
# Get a resource object from arguments
|
|
233
216
|
# If block is given, it creates a resource class with the block
|
|
234
217
|
# Otherwise, it behaves depending on `with` argument
|
|
235
218
|
#
|
|
236
219
|
# @param object [Object] the object whose class name is used for inferring resource class
|
|
220
|
+
# @param params [Hash] user-given Hash for arbitrary data
|
|
237
221
|
# @param with [:inference, Proc, Class<Alba::Resource>] determines how to get resource class for `object`
|
|
238
222
|
# When it's `:inference`, it infers resource class from `object`'s class name
|
|
239
223
|
# When it's a Proc, it calls the Proc with `object` as an argument
|
|
@@ -241,13 +225,13 @@ module Alba
|
|
|
241
225
|
# Otherwise, it raises an ArgumentError
|
|
242
226
|
# @return [Alba::Resource] resource class with `object` as its target object
|
|
243
227
|
# @raise [ArgumentError] if `with` argument is not one of `:inference`, Proc or Class
|
|
244
|
-
def resource_for(object, with: :inference, &block)
|
|
245
|
-
_resource_for(object, with: with, &block)
|
|
228
|
+
def resource_for(object, params: {}, with: :inference, &block)
|
|
229
|
+
_resource_for(object, params: params, with: with, &block)
|
|
246
230
|
end
|
|
247
231
|
|
|
248
232
|
private
|
|
249
233
|
|
|
250
|
-
def _resource_for(object, with: :inference, &block) # rubocop:disable Metrics/MethodLength
|
|
234
|
+
def _resource_for(object, params: {}, with: :inference, &block) # rubocop:disable Metrics/MethodLength
|
|
251
235
|
klass = if block
|
|
252
236
|
resource_class(&block)
|
|
253
237
|
else
|
|
@@ -259,7 +243,7 @@ module Alba
|
|
|
259
243
|
end
|
|
260
244
|
end
|
|
261
245
|
|
|
262
|
-
klass.new(object)
|
|
246
|
+
klass.new(object, params: params)
|
|
263
247
|
end
|
|
264
248
|
|
|
265
249
|
def inflector_from(name_or_module)
|
|
@@ -336,6 +320,10 @@ module Alba
|
|
|
336
320
|
@_transformed_keys = Hash.new { |h, k| h[k] = {} }
|
|
337
321
|
end
|
|
338
322
|
|
|
323
|
+
def resolved_default_superclass
|
|
324
|
+
@default_superclass.is_a?(Class) ? @default_superclass : Object.const_get(@default_superclass.to_s)
|
|
325
|
+
end
|
|
326
|
+
|
|
339
327
|
def register_default_types # rubocop:disable Metrics/AbcSize
|
|
340
328
|
[String, :String].each do |t|
|
|
341
329
|
register_type(t, check: ->(obj) { obj.is_a?(String) }, converter: lambda(&:to_s))
|
|
@@ -345,7 +333,7 @@ module Alba
|
|
|
345
333
|
end
|
|
346
334
|
register_type(:Boolean, check: ->(obj) { [true, false].include?(obj) }, converter: ->(obj) { !!obj })
|
|
347
335
|
[String, Integer].each do |t|
|
|
348
|
-
register_type(:"ArrayOf#{t}", check: ->(d) { d.is_a?(Array) && d.all?
|
|
336
|
+
register_type(:"ArrayOf#{t}", check: ->(d) { d.is_a?(Array) && d.all?(t) })
|
|
349
337
|
end
|
|
350
338
|
end
|
|
351
339
|
end
|