alba 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +10 -0
- data/.rubocop.yml +12 -2
- data/CHANGELOG.md +11 -0
- data/Gemfile +2 -2
- data/README.md +153 -5
- data/alba.gemspec +1 -1
- data/lib/alba/association.rb +7 -3
- data/lib/alba/conditional_attribute.rb +1 -0
- data/lib/alba/default_inflector.rb +13 -1
- data/lib/alba/deprecation.rb +2 -1
- data/lib/alba/layout.rb +1 -0
- data/lib/alba/nested_attribute.rb +1 -0
- data/lib/alba/resource.rb +35 -7
- data/lib/alba/typed_attribute.rb +1 -0
- data/lib/alba/version.rb +1 -1
- data/lib/alba.rb +3 -3
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89ce66083a51c7811468f9435288afbc53f81418f21635af4393eaf1ac635d14
|
4
|
+
data.tar.gz: 7344d77ba35c156a6a18abe6f5ff498b7a8cd24b460c5b3f6bf1f0739bd0c8aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33e534a676d589ba88db064b8ba57bbd10a20d268c417d8ed89fbc9b830f2861e4d3c1b46772d9151fce5dcff909e591f26f4fe1be77c247da4e1ceb4998d1cc
|
7
|
+
data.tar.gz: 401030ee3033228b11d2b75fa411809e7707b0c8b6791c2fe9da8bf9ce290c290225cb4e23895bc31019cc8cead19ac20335fffb24682c58ebc7f09a8250999a
|
data/.editorconfig
ADDED
data/.rubocop.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
|
3
3
|
inherit_gem:
|
4
|
-
rubocop-
|
4
|
+
rubocop-gem_dev: 'config/rubocop.yml'
|
5
5
|
|
6
6
|
inherit_mode:
|
7
7
|
merge:
|
@@ -18,6 +18,7 @@ AllCops:
|
|
18
18
|
- 'Rakefile'
|
19
19
|
- 'alba.gemspec'
|
20
20
|
- 'benchmark/**/*.rb'
|
21
|
+
- 'docs/**/*'
|
21
22
|
- 'script/**/*.rb'
|
22
23
|
NewCops: enable
|
23
24
|
EnabledByDefault: true
|
@@ -32,6 +33,10 @@ Layout/ClassStructure:
|
|
32
33
|
Exclude:
|
33
34
|
- 'test/**/*'
|
34
35
|
|
36
|
+
# LineLength 80 comes from restrictions in good old days.
|
37
|
+
Layout/LineLength:
|
38
|
+
Max: 160
|
39
|
+
|
35
40
|
# We'd like to write something like:
|
36
41
|
# assert_equal(
|
37
42
|
# expected,
|
@@ -73,6 +78,11 @@ Metrics/ParameterLists:
|
|
73
78
|
Minitest/EmptyLineBeforeAssertionMethods:
|
74
79
|
Enabled: false
|
75
80
|
|
81
|
+
# By nature of that test
|
82
|
+
Minitest/NoTestCases:
|
83
|
+
Exclude:
|
84
|
+
- 'test/dependencies/test_dependencies.rb'
|
85
|
+
|
76
86
|
# We need to eval resource code to test errors on resource classes
|
77
87
|
Security/Eval:
|
78
88
|
Exclude:
|
@@ -109,7 +119,7 @@ Style/InlineComment:
|
|
109
119
|
Enabled: false
|
110
120
|
|
111
121
|
Style/MethodCallWithArgsParentheses:
|
112
|
-
AllowedMethods: ['require', 'require_relative', 'include', 'extend', 'puts', 'p', 'warn', 'raise', 'send', 'public_send']
|
122
|
+
AllowedMethods: ['require', 'require_relative', 'include', 'extend', 'puts', 'p', 'warn', 'raise', 'send', 'public_send', 'alias_method']
|
113
123
|
Exclude:
|
114
124
|
# There are so many `attributes` call without parenthese and that's absolutely fine
|
115
125
|
- 'test/**/*.rb'
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [2.4.0] 2023-08-02
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Implement helper [#322](https://github.com/okuramasafumi/alba/pull/322)
|
14
|
+
- Add `prefer_resource_method!` [#323](https://github.com/okuramasafumi/alba/pull/323)
|
15
|
+
|
16
|
+
### Fixed
|
17
|
+
|
18
|
+
- Fix the bug of resource name inference [No PR](https://github.com/okuramasafumi/alba/commit/dab7091efa4a76ce9e538e08efa7349c296a705c)
|
19
|
+
|
9
20
|
## [2.3.0] 2023-04-24
|
10
21
|
|
11
22
|
### Added
|
data/Gemfile
CHANGED
@@ -10,13 +10,13 @@ gem 'minitest', '~> 5.14' # For test
|
|
10
10
|
gem 'railties', require: false # For Rails integration testing
|
11
11
|
gem 'rake', '~> 13.0' # For test and automation
|
12
12
|
gem 'rubocop', '>= 0.79.0', require: false # For lint
|
13
|
+
gem 'rubocop-gem_dev', '>= 0.3.0', require: false # For lint
|
13
14
|
gem 'rubocop-md', '~> 1.0', require: false # For lint
|
14
15
|
gem 'rubocop-minitest', '>= 0.25.0', require: false # For lint
|
15
16
|
gem 'rubocop-performance', '>= 1.15.0', require: false # For lint
|
16
17
|
gem 'rubocop-rake', '>= 0.5.1', require: false # For lint
|
17
|
-
gem 'rubocop-sensible', '~> 0.3.0', require: false # For lint
|
18
18
|
gem 'ruby-lsp', require: false # For language server
|
19
|
-
gem 'simplecov', '~> 0.
|
19
|
+
gem 'simplecov', '~> 0.22.0', require: false # For test coverage
|
20
20
|
gem 'simplecov-cobertura', require: false # For test coverage
|
21
21
|
# gem 'steep', require: false # For language server and typing
|
22
22
|
# gem 'typeprof', require: false # For language server and typing
|
data/README.md
CHANGED
@@ -11,6 +11,40 @@
|
|
11
11
|
|
12
12
|
Alba is a JSON serializer for Ruby, JRuby, and TruffleRuby.
|
13
13
|
|
14
|
+
## TL;DR
|
15
|
+
|
16
|
+
Alba allows you to do something like below.
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
class User
|
20
|
+
attr_accessor :id, :name, :email
|
21
|
+
|
22
|
+
def initialize(id, name, email)
|
23
|
+
@id = id
|
24
|
+
@name = name
|
25
|
+
@email = email
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class UserResource
|
30
|
+
include Alba::Resource
|
31
|
+
|
32
|
+
root_key :user
|
33
|
+
|
34
|
+
attributes :id, :name
|
35
|
+
|
36
|
+
attribute :name_with_email do |resource|
|
37
|
+
"#{resource.name}: #{resource.email}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
user = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
|
42
|
+
UserResource.new(user).serialize
|
43
|
+
# => '{"user":{"id":1,"name":"Masafumi OKURA","name_with_email":"Masafumi OKURA: masafumi@example.com"}}'
|
44
|
+
```
|
45
|
+
|
46
|
+
Seems useful? Continue reading!
|
47
|
+
|
14
48
|
## Discussions
|
15
49
|
|
16
50
|
Alba uses [GitHub Discussions](https://github.com/okuramasafumi/alba/discussions) to openly discuss the project.
|
@@ -82,7 +116,7 @@ You can find the documentation on [RubyDoc](https://rubydoc.info/github/okuramas
|
|
82
116
|
* Error handling
|
83
117
|
* Nil handling
|
84
118
|
* Circular associations control
|
85
|
-
*
|
119
|
+
* Types for validation and conversion
|
86
120
|
* Layout
|
87
121
|
* No runtime dependencies
|
88
122
|
|
@@ -235,6 +269,72 @@ class UserResource
|
|
235
269
|
end
|
236
270
|
```
|
237
271
|
|
272
|
+
#### Prefer methods on resource
|
273
|
+
|
274
|
+
By default, Alba prefers methods on the object to methods on the resource. This means if you have a following situation:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
class User
|
278
|
+
attr_accessor :id, :name, :email
|
279
|
+
|
280
|
+
def initialize(id, name, email)
|
281
|
+
@id = id
|
282
|
+
@name = name
|
283
|
+
@email = email
|
284
|
+
end
|
285
|
+
|
286
|
+
def name_with_email
|
287
|
+
"dummy!"
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
class UserResource
|
292
|
+
include Alba::Resource
|
293
|
+
|
294
|
+
root_key :user, :users # Later is for plural
|
295
|
+
|
296
|
+
attributes :id, :name, :name_with_email
|
297
|
+
|
298
|
+
# Same method exists in `User` class!
|
299
|
+
# This is not called
|
300
|
+
def name_with_email(user)
|
301
|
+
"#{user.name}: #{user.email}"
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
user = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
|
306
|
+
UserResource.new(user).serialize
|
307
|
+
# => '{"user":{"id":1,"name":"Masafumi OKURA","name_with_email":"dummy!"}}'
|
308
|
+
```
|
309
|
+
|
310
|
+
You can see that `name_with_email` is now `dummy!` from `User#name_with_email`. You cna change this behavior by using `prefer_resource_method!` DSL in a resource class:
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
# With the same `User` class
|
314
|
+
|
315
|
+
class UserResource
|
316
|
+
include Alba::Resource
|
317
|
+
|
318
|
+
prefer_resource_method! # This line is important
|
319
|
+
|
320
|
+
root_key :user, :users # Later is for plural
|
321
|
+
|
322
|
+
attributes :id, :name, :name_with_email
|
323
|
+
|
324
|
+
# Same method exists in `User` class!
|
325
|
+
# But now this is called!
|
326
|
+
def name_with_email(user)
|
327
|
+
"#{user.name}: #{user.email}"
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
user = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
|
332
|
+
UserResource.new(user).serialize
|
333
|
+
# => '{"user":{"id":1,"name":"Masafumi OKURA","name_with_email":"Masafumi OKURA: masafumi@example.com"}}'
|
334
|
+
```
|
335
|
+
|
336
|
+
The next major version of Alba will change this default behavior to prefer resource methods. In case you want to preserve current behavior, there's `prefer_object_method!` DSL, which does that.
|
337
|
+
|
238
338
|
#### Params
|
239
339
|
|
240
340
|
You can pass a Hash to the resource for internal use. It can be used as "flags" to control attribute content.
|
@@ -1070,6 +1170,11 @@ UserResource.new(User.new(1)).serialize
|
|
1070
1170
|
# => '{"user":{"id":1,"name":"User1","age":20}}'
|
1071
1171
|
```
|
1072
1172
|
|
1173
|
+
Note that `on_nil` does NOT work when the given object itself is `nil`. There are a few possible ways to deal with `nil`.
|
1174
|
+
|
1175
|
+
- Use `if` statement and avoid using Alba when the object is `nil`
|
1176
|
+
- Use "Null Object" pattern
|
1177
|
+
|
1073
1178
|
### Metadata
|
1074
1179
|
|
1075
1180
|
You can set a metadata with `meta` DSL or `meta` option.
|
@@ -1233,12 +1338,12 @@ In case you don't want to have a file for layout, Alba lets you define and apply
|
|
1233
1338
|
```ruby
|
1234
1339
|
class FooResource
|
1235
1340
|
include Alba::Resource
|
1236
|
-
layout inline: proc
|
1341
|
+
layout inline: proc {
|
1237
1342
|
{
|
1238
1343
|
header: 'my header',
|
1239
1344
|
body: serializable_hash
|
1240
1345
|
}
|
1241
|
-
|
1346
|
+
}
|
1242
1347
|
end
|
1243
1348
|
```
|
1244
1349
|
|
@@ -1249,12 +1354,12 @@ You can also use a Proc which returns String, not a Hash, for an inline layout.
|
|
1249
1354
|
```ruby
|
1250
1355
|
class FooResource
|
1251
1356
|
include Alba::Resource
|
1252
|
-
layout inline: proc
|
1357
|
+
layout inline: proc {
|
1253
1358
|
%({
|
1254
1359
|
"header": "my header",
|
1255
1360
|
"body": #{serialized_json}
|
1256
1361
|
})
|
1257
|
-
|
1362
|
+
}
|
1258
1363
|
end
|
1259
1364
|
```
|
1260
1365
|
|
@@ -1262,6 +1367,49 @@ It looks similar to file layout but you must use string interpolation for method
|
|
1262
1367
|
|
1263
1368
|
Also note that we use percentage notation here to use double quotes. Using single quotes in inline string layout causes the error which might be resolved in other ways.
|
1264
1369
|
|
1370
|
+
### Helper
|
1371
|
+
|
1372
|
+
Inheritance works well in most of the cases to share behaviors. One of the exceptions is when you want to shared behaviors with inline association. For example:
|
1373
|
+
|
1374
|
+
```ruby
|
1375
|
+
class ApplicationResource
|
1376
|
+
include Alba::Resource
|
1377
|
+
|
1378
|
+
def self.with_id
|
1379
|
+
attributes :id
|
1380
|
+
end
|
1381
|
+
end
|
1382
|
+
|
1383
|
+
class LibraryResource < ApplicationResource
|
1384
|
+
with_id
|
1385
|
+
attributes :created_at
|
1386
|
+
|
1387
|
+
with_many :library_books do
|
1388
|
+
with_id # This DOES NOT work!
|
1389
|
+
attributes :created_at
|
1390
|
+
end
|
1391
|
+
end
|
1392
|
+
```
|
1393
|
+
|
1394
|
+
This doesn't work. Technically, inside of `has_many` is a separate class which doesn't inherit from the base class (`LibraryResource` in this example).
|
1395
|
+
|
1396
|
+
`helper` solves this problem. It's just a mark for methods that should be shared with inline associations.
|
1397
|
+
|
1398
|
+
```ruby
|
1399
|
+
class ApplicationResource
|
1400
|
+
include Alba::Resource
|
1401
|
+
|
1402
|
+
helper do
|
1403
|
+
def with_id
|
1404
|
+
attributes :id
|
1405
|
+
end
|
1406
|
+
end
|
1407
|
+
end
|
1408
|
+
# Now `LibraryResource` works!
|
1409
|
+
```
|
1410
|
+
|
1411
|
+
Within `helper` block, all methods should be defined without `self.`.
|
1412
|
+
|
1265
1413
|
### Caching
|
1266
1414
|
|
1267
1415
|
Currently, Alba doesn't support caching, primarily due to the behavior of `ActiveRecord::Relation`'s cache. See [the issue](https://github.com/rails/rails/issues/41784).
|
data/alba.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
14
14
|
|
15
15
|
spec.metadata = {
|
16
|
-
'bug_tracker_uri' => 'https://github.com/okuramasafumi/issues',
|
16
|
+
'bug_tracker_uri' => 'https://github.com/okuramasafumi/alba/issues',
|
17
17
|
'changelog_uri' => 'https://github.com/okuramasafumi/alba/blob/main/CHANGELOG.md',
|
18
18
|
'documentation_uri' => 'https://rubydoc.info/github/okuramasafumi/alba',
|
19
19
|
'source_code_uri' => 'https://github.com/okuramasafumi/alba',
|
data/lib/alba/association.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
module Alba
|
2
2
|
# Representing association
|
3
|
+
# @api private
|
3
4
|
class Association
|
4
5
|
@const_cache = {}
|
5
6
|
class << self
|
7
|
+
# cache for `const_get`
|
6
8
|
attr_reader :const_cache
|
7
9
|
end
|
8
10
|
|
@@ -14,15 +16,16 @@ module Alba
|
|
14
16
|
# @param params [Hash] params override for the association
|
15
17
|
# @param nesting [String] a namespace where source class is inferred with
|
16
18
|
# @param key_transformation [Symbol] key transformation type
|
19
|
+
# @param helper [Module] helper module to include
|
17
20
|
# @param block [Block] used to define resource when resource arg is absent
|
18
|
-
def initialize(name:, condition: nil, resource: nil, params: {}, nesting: nil, key_transformation: :none, &block)
|
21
|
+
def initialize(name:, condition: nil, resource: nil, params: {}, nesting: nil, key_transformation: :none, helper: nil, &block)
|
19
22
|
@name = name
|
20
23
|
@condition = condition
|
21
24
|
@resource = resource
|
22
25
|
@params = params
|
23
26
|
return if @resource
|
24
27
|
|
25
|
-
assign_resource(nesting, key_transformation, block)
|
28
|
+
assign_resource(nesting, key_transformation, block, helper)
|
26
29
|
end
|
27
30
|
|
28
31
|
# Recursively converts an object into a Hash
|
@@ -59,9 +62,10 @@ module Alba
|
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
62
|
-
def assign_resource(nesting, key_transformation, block)
|
65
|
+
def assign_resource(nesting, key_transformation, block, helper) # rubocop:disable Metrics/MethodLength
|
63
66
|
@resource = if block
|
64
67
|
klass = Alba.resource_class
|
68
|
+
klass.helper(helper) if helper
|
65
69
|
klass.transform_keys(key_transformation)
|
66
70
|
klass.class_eval(&block)
|
67
71
|
klass
|
@@ -3,6 +3,7 @@ require_relative 'constants'
|
|
3
3
|
|
4
4
|
module Alba
|
5
5
|
# Represents attribute with `if` option
|
6
|
+
# @api private
|
6
7
|
class ConditionalAttribute
|
7
8
|
# @param body [Symbol, Proc, Alba::Association, Alba::TypedAttribute] real attribute wrapped with condition
|
8
9
|
# @param condition [Symbol, Proc] condition to check
|
@@ -2,7 +2,7 @@ begin
|
|
2
2
|
require 'active_support/inflector'
|
3
3
|
require 'active_support/core_ext/module/delegation'
|
4
4
|
rescue LoadError
|
5
|
-
raise
|
5
|
+
raise Alba::Error, 'To use default inflector, please install `ActiveSupport` gem.'
|
6
6
|
end
|
7
7
|
|
8
8
|
module Alba
|
@@ -11,6 +11,18 @@ module Alba
|
|
11
11
|
# Another is that `ActiveSupport::Inflector` doesn't have `camelize_lower` method that we want it to have, so this module works as an adapter.
|
12
12
|
module DefaultInflector
|
13
13
|
class << self
|
14
|
+
# @!method camelize(key)
|
15
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-camelize ActiveSupport::Inflector#camelize
|
16
|
+
# @!method dasherize(key)
|
17
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-dasherize ActiveSupport::Inflector#dasherize
|
18
|
+
# @!method underscore(key)
|
19
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-underscore ActiveSupport::Inflector#underscore
|
20
|
+
# @!method classify(key)
|
21
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-classify ActiveSupport::Inflector#classify
|
22
|
+
# @!method demodulize(key)
|
23
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-demodulize ActiveSupport::Inflector#demodulize
|
24
|
+
# @!method pluralize(key)
|
25
|
+
# @see https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-pluralize ActiveSupport::Inflector#pluralize
|
14
26
|
delegate :camelize, :dasherize, :underscore, :classify, :demodulize, :pluralize, to: ActiveSupport::Inflector
|
15
27
|
end
|
16
28
|
|
data/lib/alba/deprecation.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Alba
|
2
2
|
# Module for printing deprecation warning
|
3
|
+
# @api private
|
3
4
|
module Deprecation
|
4
|
-
# Similar to {
|
5
|
+
# Similar to {#warn} but prints caller as well
|
5
6
|
#
|
6
7
|
# @param message [String] main message to print
|
7
8
|
# @return void
|
data/lib/alba/layout.rb
CHANGED
data/lib/alba/resource.rb
CHANGED
@@ -11,7 +11,7 @@ module Alba
|
|
11
11
|
module Resource
|
12
12
|
# @!parse include InstanceMethods
|
13
13
|
# @!parse extend ClassMethods
|
14
|
-
DSLS = {_attributes: {}, _key: nil, _key_for_collection: nil, _meta: nil, _transform_type: :none, _transforming_root_key: false, _key_transformation_cascade: true, _on_error: nil, _on_nil: nil, _layout: nil, _collection_key: nil}.freeze # rubocop:disable Layout/LineLength
|
14
|
+
DSLS = {_attributes: {}, _key: nil, _key_for_collection: nil, _meta: nil, _transform_type: :none, _transforming_root_key: false, _key_transformation_cascade: true, _on_error: nil, _on_nil: nil, _layout: nil, _collection_key: nil, _helper: nil}.freeze # rubocop:disable Layout/LineLength
|
15
15
|
private_constant :DSLS
|
16
16
|
|
17
17
|
WITHIN_DEFAULT = Object.new.freeze
|
@@ -80,7 +80,7 @@ module Alba
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
# Returns a Hash correspondng {
|
83
|
+
# Returns a Hash correspondng {#serialize}
|
84
84
|
#
|
85
85
|
# @param root_key [Symbol, nil, true]
|
86
86
|
# @param meta [Hash] metadata for this seialization
|
@@ -260,18 +260,28 @@ module Alba
|
|
260
260
|
when TypedAttribute then attribute.value(obj)
|
261
261
|
when NestedAttribute then attribute.value(object: obj, params: params)
|
262
262
|
when ConditionalAttribute then attribute.with_passing_condition(resource: self, object: obj) { |attr| fetch_attribute(obj, key, attr) }
|
263
|
-
else
|
264
|
-
raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
|
263
|
+
else raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
|
265
264
|
end
|
266
265
|
value.nil? && nil_handler ? instance_exec(obj, key, attribute, &nil_handler) : value
|
267
266
|
end
|
268
267
|
|
268
|
+
# TODO: from version 3, `_fetch_attribute_from_resource_first` is default
|
269
269
|
def fetch_attribute_from_object_and_resource(obj, attribute)
|
270
|
+
_fetch_attribute_from_object_first(obj, attribute)
|
271
|
+
end
|
272
|
+
|
273
|
+
def _fetch_attribute_from_object_first(obj, attribute)
|
270
274
|
obj.__send__(attribute)
|
271
275
|
rescue NoMethodError
|
272
276
|
__send__(attribute, obj)
|
273
277
|
end
|
274
278
|
|
279
|
+
def _fetch_attribute_from_resource_first(obj, attribute)
|
280
|
+
__send__(attribute, obj)
|
281
|
+
rescue NoMethodError
|
282
|
+
obj.__send__(attribute)
|
283
|
+
end
|
284
|
+
|
275
285
|
def nil_handler
|
276
286
|
@_on_nil
|
277
287
|
end
|
@@ -374,8 +384,7 @@ module Alba
|
|
374
384
|
def association(name, condition = nil, resource: nil, key: nil, params: {}, **options, &block)
|
375
385
|
key_transformation = @_key_transformation_cascade ? @_transform_type : :none
|
376
386
|
assoc = Association.new(
|
377
|
-
name: name, condition: condition, resource: resource, params: params, nesting: nesting, key_transformation: key_transformation,
|
378
|
-
&block
|
387
|
+
name: name, condition: condition, resource: resource, params: params, nesting: nesting, key_transformation: key_transformation, helper: @_helper, &block
|
379
388
|
)
|
380
389
|
@_attributes[key&.to_sym || name.to_sym] = options[:if] ? ConditionalAttribute.new(body: assoc, condition: options[:if]) : assoc
|
381
390
|
end
|
@@ -388,7 +397,7 @@ module Alba
|
|
388
397
|
if name.nil?
|
389
398
|
nil
|
390
399
|
else
|
391
|
-
name.rpartition('::').first.
|
400
|
+
name.rpartition('::').first.then { |n| n.empty? ? nil : n }
|
392
401
|
end
|
393
402
|
end
|
394
403
|
private :nesting
|
@@ -503,6 +512,25 @@ module Alba
|
|
503
512
|
def on_nil(&block)
|
504
513
|
@_on_nil = block
|
505
514
|
end
|
515
|
+
|
516
|
+
# Define helper methods
|
517
|
+
#
|
518
|
+
# @param mod [Module] a module to extend
|
519
|
+
def helper(mod = @_helper || Module.new, &block)
|
520
|
+
mod.module_eval(&block) if block
|
521
|
+
extend mod
|
522
|
+
@_helper = mod
|
523
|
+
end
|
524
|
+
|
525
|
+
# DSL for alias, purely for readability
|
526
|
+
def prefer_resource_method!
|
527
|
+
alias_method :fetch_attribute_from_object_and_resource, :_fetch_attribute_from_resource_first
|
528
|
+
end
|
529
|
+
|
530
|
+
# DSL for alias, purely for readability
|
531
|
+
def prefer_object_method!
|
532
|
+
alias_method :fetch_attribute_from_object_and_resource, :_fetch_attribute_from_object_first
|
533
|
+
end
|
506
534
|
end
|
507
535
|
end
|
508
536
|
end
|
data/lib/alba/typed_attribute.rb
CHANGED
data/lib/alba/version.rb
CHANGED
data/lib/alba.rb
CHANGED
@@ -66,7 +66,7 @@ module Alba
|
|
66
66
|
# @param with [Symbol, Class, Module] inflector
|
67
67
|
# When it's a Symbol, it sets inflector with given name
|
68
68
|
# When it's a Class or a Module, it sets given object to inflector
|
69
|
-
# @deprecated Use {
|
69
|
+
# @deprecated Use {.inflector=} instead
|
70
70
|
def enable_inference!(with:)
|
71
71
|
Alba::Deprecation.warn('Alba.enable_inference! is deprecated. Use `Alba.inflector=` instead.')
|
72
72
|
@inflector = inflector_from(with)
|
@@ -75,14 +75,14 @@ module Alba
|
|
75
75
|
|
76
76
|
# Disable inference for key and resource name
|
77
77
|
#
|
78
|
-
# @deprecated Use {
|
78
|
+
# @deprecated Use {.inflector=} instead
|
79
79
|
def disable_inference!
|
80
80
|
Alba::Deprecation.warn('Alba.disable_inference! is deprecated. Use `Alba.inflector = nil` instead.')
|
81
81
|
@inferring = false
|
82
82
|
@inflector = nil
|
83
83
|
end
|
84
84
|
|
85
|
-
# @deprecated Use {
|
85
|
+
# @deprecated Use {.inflector} instead
|
86
86
|
# @return [Boolean] whether inference is enabled or not
|
87
87
|
def inferring
|
88
88
|
Alba::Deprecation.warn('Alba.inferring is deprecated. Use `Alba.inflector` instead.')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OKURA Masafumi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Alba is the fastest JSON serializer for Ruby. It focuses on performance,
|
14
14
|
flexibility and usability.
|
@@ -19,6 +19,7 @@ extensions: []
|
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
21
|
- ".codeclimate.yml"
|
22
|
+
- ".editorconfig"
|
22
23
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
23
24
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
24
25
|
- ".github/dependabot.yml"
|
@@ -71,7 +72,7 @@ homepage: https://github.com/okuramasafumi/alba
|
|
71
72
|
licenses:
|
72
73
|
- MIT
|
73
74
|
metadata:
|
74
|
-
bug_tracker_uri: https://github.com/okuramasafumi/issues
|
75
|
+
bug_tracker_uri: https://github.com/okuramasafumi/alba/issues
|
75
76
|
changelog_uri: https://github.com/okuramasafumi/alba/blob/main/CHANGELOG.md
|
76
77
|
documentation_uri: https://rubydoc.info/github/okuramasafumi/alba
|
77
78
|
source_code_uri: https://github.com/okuramasafumi/alba
|
@@ -91,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
92
|
- !ruby/object:Gem::Version
|
92
93
|
version: '0'
|
93
94
|
requirements: []
|
94
|
-
rubygems_version: 3.4.
|
95
|
+
rubygems_version: 3.4.14
|
95
96
|
signing_key:
|
96
97
|
specification_version: 4
|
97
98
|
summary: Alba is the fastest JSON serializer for Ruby.
|