alba 0.10.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -5
- data/.travis.yml +1 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -4
- data/Gemfile.lock +41 -38
- data/README.md +69 -5
- data/alba.gemspec +1 -1
- data/lib/alba.rb +23 -6
- data/lib/alba/association.rb +7 -2
- data/lib/alba/key_transformer.rb +31 -0
- data/lib/alba/many.rb +7 -2
- data/lib/alba/one.rb +7 -2
- data/lib/alba/resource.rb +97 -20
- data/lib/alba/serializer.rb +26 -6
- data/lib/alba/version.rb +1 -1
- data/sider.yml +1 -0
- metadata +6 -6
- data/lib/alba/resources/default_resource.rb +0 -13
- data/lib/alba/serializers/default_serializer.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4a5b866825838f457bb17c0c1037f68c3e88a9b96c86dd9e0c456d101f69158
|
4
|
+
data.tar.gz: d1f451fff558385b3ae4610355a3abb9aced052ce138eff9913169a12c8a23c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71fdab1911c6fc9e1ba88e8cbdc553311b99aecd975462b05958e5be1e491aa10734b6b6f6f15f24ae98c8ab5a1b1021d6c544a172befcedd23ca80283529e98
|
7
|
+
data.tar.gz: 05f06f2e7f3ec93e0a616bec6e3d71a90590b68c7ce397050bb9c019d2bbf206b070ed1cf44603cd301fa5dd2634df50c4e08b75a8c478b2f0063b6551b5bdcc
|
data/.rubocop.yml
CHANGED
@@ -6,6 +6,7 @@ inherit_gem:
|
|
6
6
|
require:
|
7
7
|
- rubocop-minitest
|
8
8
|
- rubocop-performance
|
9
|
+
- rubocop-rake
|
9
10
|
|
10
11
|
AllCops:
|
11
12
|
Exclude:
|
@@ -18,9 +19,6 @@ AllCops:
|
|
18
19
|
Bundler/GemComment:
|
19
20
|
Enabled: false
|
20
21
|
|
21
|
-
Layout/ClassStructure:
|
22
|
-
Enabled: true
|
23
|
-
|
24
22
|
Layout/SpaceInsideHashLiteralBraces:
|
25
23
|
EnforcedStyle: no_space
|
26
24
|
|
@@ -38,12 +36,14 @@ Metrics/MethodLength:
|
|
38
36
|
Max: 15
|
39
37
|
|
40
38
|
Style/ConstantVisibility:
|
41
|
-
|
39
|
+
Exclude:
|
40
|
+
- 'lib/alba/version.rb'
|
42
41
|
|
43
42
|
Style/Copyright:
|
44
43
|
Enabled: false
|
45
44
|
|
46
|
-
|
45
|
+
# I know what I do :)
|
46
|
+
Style/DisableCopsWithinSourceCodeDirective:
|
47
47
|
Enabled: false
|
48
48
|
|
49
49
|
Style/FrozenStringLiteralComment:
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/Gemfile
CHANGED
@@ -5,10 +5,12 @@ gemspec
|
|
5
5
|
|
6
6
|
gem 'activesupport', require: false # For backend
|
7
7
|
gem 'coveralls', require: false # For test coverage
|
8
|
-
gem 'minitest', '~> 5.
|
9
|
-
gem 'oj', '~> 3.
|
8
|
+
gem 'minitest', '~> 5.14' # For test
|
9
|
+
gem 'oj', '~> 3.11', platform: :ruby, require: false # For backend
|
10
10
|
gem 'rake', '~> 13.0' # For test and automation
|
11
11
|
gem 'rubocop', '>= 0.79.0', require: false # For lint
|
12
|
-
gem 'rubocop-minitest', '~> 0.10.
|
13
|
-
gem 'rubocop-performance', '~> 1.
|
12
|
+
gem 'rubocop-minitest', '~> 0.10.3', require: false # For lint
|
13
|
+
gem 'rubocop-performance', '~> 1.9.2', require: false # For lint
|
14
|
+
gem 'rubocop-rake', '>= 0.5.1', require: false # For lint
|
14
15
|
gem 'rubocop-sensible', '~> 0.3.0', require: false # For lint
|
16
|
+
gem 'yard', require: false
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
alba (0.
|
4
|
+
alba (0.13.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
activesupport (6.
|
9
|
+
activesupport (6.1.1)
|
10
10
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
|
-
i18n (>=
|
12
|
-
minitest (
|
13
|
-
tzinfo (~>
|
14
|
-
zeitwerk (~> 2.
|
11
|
+
i18n (>= 1.6, < 2)
|
12
|
+
minitest (>= 5.1)
|
13
|
+
tzinfo (~> 2.0)
|
14
|
+
zeitwerk (~> 2.3)
|
15
15
|
ast (2.4.1)
|
16
|
-
|
17
|
-
concurrent-ruby (1.1.6)
|
16
|
+
concurrent-ruby (1.1.7)
|
18
17
|
coveralls (0.8.23)
|
19
18
|
json (>= 1.8, < 3)
|
20
19
|
simplecov (~> 0.16.1)
|
@@ -22,37 +21,39 @@ GEM
|
|
22
21
|
thor (>= 0.19.4, < 2.0)
|
23
22
|
tins (~> 1.6)
|
24
23
|
docile (1.3.2)
|
25
|
-
i18n (1.8.
|
24
|
+
i18n (1.8.7)
|
26
25
|
concurrent-ruby (~> 1.0)
|
27
26
|
json (2.3.1)
|
28
|
-
minitest (5.14.
|
29
|
-
oj (3.
|
30
|
-
|
31
|
-
|
32
|
-
parser (2.7.1.4)
|
27
|
+
minitest (5.14.3)
|
28
|
+
oj (3.11.0)
|
29
|
+
parallel (1.20.1)
|
30
|
+
parser (3.0.0.0)
|
33
31
|
ast (~> 2.4.1)
|
34
32
|
rainbow (3.0.0)
|
35
|
-
rake (13.0.
|
36
|
-
regexp_parser (
|
33
|
+
rake (13.0.3)
|
34
|
+
regexp_parser (2.0.3)
|
37
35
|
rexml (3.2.4)
|
38
|
-
rubocop (
|
36
|
+
rubocop (1.8.1)
|
39
37
|
parallel (~> 1.10)
|
40
|
-
parser (>=
|
38
|
+
parser (>= 3.0.0.0)
|
41
39
|
rainbow (>= 2.2.2, < 4.0)
|
42
|
-
regexp_parser (>= 1.
|
40
|
+
regexp_parser (>= 1.8, < 3.0)
|
43
41
|
rexml
|
44
|
-
rubocop-ast (>=
|
42
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
45
43
|
ruby-progressbar (~> 1.7)
|
46
|
-
unicode-display_width (>= 1.4.0, <
|
47
|
-
rubocop-ast (
|
48
|
-
parser (>= 2.7.1.
|
49
|
-
rubocop-minitest (0.10.
|
50
|
-
rubocop (>= 0.87)
|
51
|
-
rubocop-performance (1.
|
52
|
-
rubocop (>= 0.
|
44
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
45
|
+
rubocop-ast (1.4.0)
|
46
|
+
parser (>= 2.7.1.5)
|
47
|
+
rubocop-minitest (0.10.3)
|
48
|
+
rubocop (>= 0.87, < 2.0)
|
49
|
+
rubocop-performance (1.9.2)
|
50
|
+
rubocop (>= 0.90.0, < 2.0)
|
51
|
+
rubocop-ast (>= 0.4.0)
|
52
|
+
rubocop-rake (0.5.1)
|
53
|
+
rubocop
|
53
54
|
rubocop-sensible (0.3.0)
|
54
55
|
rubocop (>= 0.60.0)
|
55
|
-
ruby-progressbar (1.
|
56
|
+
ruby-progressbar (1.11.0)
|
56
57
|
simplecov (0.16.1)
|
57
58
|
docile (~> 1.1)
|
58
59
|
json (>= 1.8, < 3)
|
@@ -62,13 +63,13 @@ GEM
|
|
62
63
|
term-ansicolor (1.7.1)
|
63
64
|
tins (~> 1.0)
|
64
65
|
thor (1.0.1)
|
65
|
-
thread_safe (0.3.6)
|
66
66
|
tins (1.25.0)
|
67
67
|
sync
|
68
|
-
tzinfo (
|
69
|
-
|
70
|
-
unicode-display_width (
|
71
|
-
|
68
|
+
tzinfo (2.0.4)
|
69
|
+
concurrent-ruby (~> 1.0)
|
70
|
+
unicode-display_width (2.0.0)
|
71
|
+
yard (0.9.26)
|
72
|
+
zeitwerk (2.4.2)
|
72
73
|
|
73
74
|
PLATFORMS
|
74
75
|
ruby
|
@@ -77,13 +78,15 @@ DEPENDENCIES
|
|
77
78
|
activesupport
|
78
79
|
alba!
|
79
80
|
coveralls
|
80
|
-
minitest (~> 5.
|
81
|
-
oj (~> 3.
|
81
|
+
minitest (~> 5.14)
|
82
|
+
oj (~> 3.11)
|
82
83
|
rake (~> 13.0)
|
83
84
|
rubocop (>= 0.79.0)
|
84
|
-
rubocop-minitest (~> 0.10.
|
85
|
-
rubocop-performance (~> 1.
|
85
|
+
rubocop-minitest (~> 0.10.3)
|
86
|
+
rubocop-performance (~> 1.9.2)
|
87
|
+
rubocop-rake (>= 0.5.1)
|
86
88
|
rubocop-sensible (~> 0.3.0)
|
89
|
+
yard
|
87
90
|
|
88
91
|
BUNDLED WITH
|
89
|
-
2.
|
92
|
+
2.2.6
|
data/README.md
CHANGED
@@ -2,24 +2,26 @@
|
|
2
2
|
[![Build Status](https://travis-ci.com/okuramasafumi/alba.svg?branch=master)](https://travis-ci.com/okuramasafumi/alba)
|
3
3
|
[![Coverage Status](https://coveralls.io/repos/github/okuramasafumi/alba/badge.svg?branch=master)](https://coveralls.io/github/okuramasafumi/alba?branch=master)
|
4
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/fdab4cc0de0b9addcfe8/maintainability)](https://codeclimate.com/github/okuramasafumi/alba/maintainability)
|
5
|
+
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/okuramasafumi/alba)
|
6
|
+
![GitHub](https://img.shields.io/github/license/okuramasafumi/alba)
|
5
7
|
|
6
8
|
# Alba
|
7
9
|
|
8
10
|
`Alba` is the fastest JSON serializer for Ruby.
|
9
11
|
|
10
|
-
|
12
|
+
## Why yet another JSON serializer?
|
11
13
|
|
12
14
|
We know that there are several other JSON serializers for Ruby around, but none of them made us satisfied.
|
13
15
|
|
14
16
|
Alba has some advantages over other JSON serializers which we've wanted to have.
|
15
17
|
|
16
|
-
|
18
|
+
### Easy to understand
|
17
19
|
|
18
20
|
DSL is great. It makes the coding experience natural and intuitive. However, remembering lots of DSL requires us a lot of effort. Unfortunately, most of the existing libraries have implemented their features via DSL and it's not easy to understand how they behave entirely. Alba's core DSL are only four (`attributes`, `attribute`, `one` and `many`) so it's easy to understand how to use.
|
19
21
|
|
20
22
|
Alba is also understandable internally. The codebase is much smaller than the alternatives. In fact, it's less than 300 lines of code. Look at the code on [GitHub](https://github.com/okuramasafumi/alba/tree/master/lib) and you'll be surprised how simple it is!
|
21
23
|
|
22
|
-
|
24
|
+
### Performance
|
23
25
|
|
24
26
|
Alba is faster than most of the alternatives. We have a [benchmark](https://gist.github.com/okuramasafumi/4e375525bd3a28e4ca812d2a3b3e5829).
|
25
27
|
|
@@ -39,6 +41,36 @@ Or install it yourself as:
|
|
39
41
|
|
40
42
|
$ gem install alba
|
41
43
|
|
44
|
+
## Supported Ruby versions
|
45
|
+
|
46
|
+
Alba supports CRuby 2.5.7 and higher and latest TruffleRuby.
|
47
|
+
|
48
|
+
## Documentation
|
49
|
+
|
50
|
+
You can find the documentation on [RubyDoc](https://rubydoc.info/gems/alba).
|
51
|
+
|
52
|
+
## Features
|
53
|
+
|
54
|
+
* Resource-based serialization
|
55
|
+
* Arbitrary attribute definition
|
56
|
+
* One and many association with the ability to define them inline
|
57
|
+
* Adding condition and filter to association
|
58
|
+
* Parameters can be injected and used in attributes and associations
|
59
|
+
* Setting root key separately in Serializer
|
60
|
+
* Adding metadata
|
61
|
+
* Selectable backend
|
62
|
+
* No runtime dependencies
|
63
|
+
|
64
|
+
## Anti features
|
65
|
+
|
66
|
+
* Sorting keys
|
67
|
+
* Class level support of parameters
|
68
|
+
* Supporting all existing JSON encoder/decoder
|
69
|
+
* Cache
|
70
|
+
* [JSON:API](https://jsonapi.org) support
|
71
|
+
* Association name inflection
|
72
|
+
* And many others
|
73
|
+
|
42
74
|
## Usage
|
43
75
|
|
44
76
|
### Configuration
|
@@ -125,7 +157,7 @@ class ArticleResource
|
|
125
157
|
attributes :title
|
126
158
|
end
|
127
159
|
|
128
|
-
class
|
160
|
+
class UserResource
|
129
161
|
include Alba::Resource
|
130
162
|
|
131
163
|
attributes :id
|
@@ -139,7 +171,7 @@ user.articles << article1
|
|
139
171
|
article2 = Article.new(2, 'Super nice', 'Really nice!')
|
140
172
|
user.articles << article2
|
141
173
|
|
142
|
-
|
174
|
+
UserResource.new(user).serialize
|
143
175
|
# => '{"id":1,"articles":[{"title":"Hello World!"},{"title":"Super nice"}]}'
|
144
176
|
```
|
145
177
|
|
@@ -189,6 +221,38 @@ RestrictedFooResouce.new(foo).serialize
|
|
189
221
|
end
|
190
222
|
```
|
191
223
|
|
224
|
+
### Attribute key transformation
|
225
|
+
|
226
|
+
** Note: You need to install `active_support` gem to use `transform_keys` DSL.
|
227
|
+
|
228
|
+
With `active_support` installed, you can transform attribute keys.
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
class User
|
232
|
+
attr_reader :id, :first_name, :last_name
|
233
|
+
|
234
|
+
def initialize(id, first_name, last_name)
|
235
|
+
@id = id
|
236
|
+
@first_name = first_name
|
237
|
+
@last_name = last_name
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
class UserResource
|
242
|
+
include Alba::Resource
|
243
|
+
|
244
|
+
attributes :id, :first_name, :last_name
|
245
|
+
|
246
|
+
transform_keys :lower_camel
|
247
|
+
end
|
248
|
+
|
249
|
+
user = User.new(1, 'Masafumi', 'Okura')
|
250
|
+
UserResourceCamel.new(user).serialize
|
251
|
+
# => '{"id":1,"firstName":"Masafumi","lastName":"Okura"}'
|
252
|
+
```
|
253
|
+
|
254
|
+
Supported transformation types are :camel, :lower_camel and :dash.
|
255
|
+
|
192
256
|
## Comparison
|
193
257
|
|
194
258
|
Alba is faster than alternatives.
|
data/alba.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = "Alba is designed to be a simple, easy to use and fast alternative to existing JSON serializers. Its performance is better than almost all gems which do similar things. The internal is so simple that it's easy to hack and maintain."
|
11
11
|
spec.homepage = 'https://github.com/okuramasafumi/alba'
|
12
12
|
spec.license = 'MIT'
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.7')
|
14
14
|
|
15
15
|
spec.metadata['homepage_uri'] = spec.homepage
|
16
16
|
spec.metadata['source_code_uri'] = 'https://github.com/okuramasafumi/alba'
|
data/lib/alba.rb
CHANGED
@@ -1,23 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'alba/resource'
|
5
|
-
require 'alba/resources/default_resource'
|
1
|
+
require_relative 'alba/version'
|
2
|
+
require_relative 'alba/serializer'
|
3
|
+
require_relative 'alba/resource'
|
6
4
|
|
7
5
|
# Core module
|
8
6
|
module Alba
|
7
|
+
# Base class for Errors
|
9
8
|
class Error < StandardError; end
|
9
|
+
|
10
|
+
# Error class for backend which is not supported
|
10
11
|
class UnsupportedBackend < Error; end
|
11
12
|
|
12
13
|
class << self
|
13
14
|
attr_reader :backend, :encoder
|
14
15
|
attr_accessor :default_serializer
|
15
16
|
|
17
|
+
# Set the backend, which actually serializes object into JSON
|
18
|
+
#
|
19
|
+
# @param backend [#to_sym, nil] the name of the backend
|
20
|
+
# Possible values are `oj`, `active_support`, `default`, `json` and nil
|
21
|
+
# @return [Proc] the proc to encode object into JSON
|
22
|
+
# @raise [Alba::UnsupportedBackend] if backend is not supported
|
16
23
|
def backend=(backend)
|
17
24
|
@backend = backend&.to_sym
|
18
25
|
set_encoder
|
19
26
|
end
|
20
27
|
|
28
|
+
# Serialize the object with inline definitions
|
29
|
+
#
|
30
|
+
# @param object [Object] the object to be serialized
|
31
|
+
# @param with [nil, Proc, Alba::Serializer] selializer
|
32
|
+
# @param block [Block] resource block
|
33
|
+
# @return [String] serialized JSON string
|
34
|
+
# @raise [ArgumentError] if block is absent or `with` argument's type is wrong
|
21
35
|
def serialize(object, with: nil, &block)
|
22
36
|
raise ArgumentError, 'Block required' unless block
|
23
37
|
|
@@ -64,7 +78,10 @@ module Alba
|
|
64
78
|
end
|
65
79
|
|
66
80
|
def resource_class
|
67
|
-
|
81
|
+
@resource_class ||= begin
|
82
|
+
klass = Class.new
|
83
|
+
klass.include(Alba::Resource)
|
84
|
+
end
|
68
85
|
end
|
69
86
|
end
|
70
87
|
|
data/lib/alba/association.rb
CHANGED
@@ -2,6 +2,10 @@ module Alba
|
|
2
2
|
# Base class for `One` and `Many`
|
3
3
|
# Child class should implement `to_hash` method
|
4
4
|
class Association
|
5
|
+
# @param name [Symbol] name of the method to fetch association
|
6
|
+
# @param condition [Proc] a proc filtering data
|
7
|
+
# @param resource [Class<Alba::Resource>] a resource class for the association
|
8
|
+
# @param block [Block] used to define resource when resource arg is absent
|
5
9
|
def initialize(name:, condition: nil, resource: nil, &block)
|
6
10
|
@name = name
|
7
11
|
@condition = condition
|
@@ -10,6 +14,7 @@ module Alba
|
|
10
14
|
raise ArgumentError, 'resource or block is required' if @resource.nil? && @block.nil?
|
11
15
|
end
|
12
16
|
|
17
|
+
# @abstract
|
13
18
|
def to_hash
|
14
19
|
:not_implemented
|
15
20
|
end
|
@@ -17,8 +22,8 @@ module Alba
|
|
17
22
|
private
|
18
23
|
|
19
24
|
def resource_class
|
20
|
-
klass =
|
21
|
-
klass.
|
25
|
+
klass = Class.new
|
26
|
+
klass.include(Alba::Resource)
|
22
27
|
klass.class_eval(&@block)
|
23
28
|
klass
|
24
29
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Alba
|
2
|
+
# Transform keys using `ActiveSupport::Inflector`
|
3
|
+
module KeyTransformer
|
4
|
+
begin
|
5
|
+
require 'active_support/inflector'
|
6
|
+
rescue LoadError
|
7
|
+
raise ::Alba::Error, 'To use transform_keys, please install `ActiveSupport` gem.'
|
8
|
+
end
|
9
|
+
|
10
|
+
module_function
|
11
|
+
|
12
|
+
# Transform key as given transform_type
|
13
|
+
#
|
14
|
+
# @params key [String] key to be transformed
|
15
|
+
# @params transform_type [Symbol] transform type
|
16
|
+
# @return [String] transformed key
|
17
|
+
# @raise [Alba::Error] when transform_type is not supported
|
18
|
+
def transform(key, transform_type)
|
19
|
+
case transform_type
|
20
|
+
when :camel
|
21
|
+
ActiveSupport::Inflector.camelize(key)
|
22
|
+
when :lower_camel
|
23
|
+
ActiveSupport::Inflector.camelize(key, false)
|
24
|
+
when :dash
|
25
|
+
ActiveSupport::Inflector.dasherize(key)
|
26
|
+
else
|
27
|
+
raise ::Alba::Error, "Unknown transform_type: #{transform_type}. Supported transform_type are :camel and :dash."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/alba/many.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
|
1
|
+
require_relative 'association'
|
2
2
|
|
3
3
|
module Alba
|
4
4
|
# Representing many association
|
5
5
|
class Many < Association
|
6
|
+
# Recursively converts objects into an Array of Hashes
|
7
|
+
#
|
8
|
+
# @param target [Object] the object having an association method
|
9
|
+
# @param params [Hash] user-given Hash for arbitrary data
|
10
|
+
# @return [Array<Hash>]
|
6
11
|
def to_hash(target, params: {})
|
7
12
|
objects = target.public_send(@name)
|
8
|
-
objects = @condition.call(objects) if @condition
|
13
|
+
objects = @condition.call(objects, params) if @condition
|
9
14
|
objects.map { |o| @resource.new(o, params: params).to_hash }
|
10
15
|
end
|
11
16
|
end
|
data/lib/alba/one.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
|
1
|
+
require_relative 'association'
|
2
2
|
|
3
3
|
module Alba
|
4
4
|
# Representing one association
|
5
5
|
class One < Association
|
6
|
+
# Recursively converts an object into a Hash
|
7
|
+
#
|
8
|
+
# @param target [Object] the object having an association method
|
9
|
+
# @param params [Hash] user-given Hash for arbitrary data
|
10
|
+
# @return [Hash]
|
6
11
|
def to_hash(target, params: {})
|
7
12
|
object = target.public_send(@name)
|
8
|
-
object = @condition.call(object) if @condition
|
13
|
+
object = @condition.call(object, params) if @condition
|
9
14
|
@resource.new(object, params: params).to_hash
|
10
15
|
end
|
11
16
|
end
|
data/lib/alba/resource.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require 'alba/serializers/default_serializer'
|
1
|
+
require_relative 'serializer'
|
2
|
+
require_relative 'one'
|
3
|
+
require_relative 'many'
|
5
4
|
|
6
5
|
module Alba
|
7
6
|
# This module represents what should be serialized
|
8
7
|
module Resource
|
9
|
-
|
8
|
+
# @!parse include InstanceMethods
|
9
|
+
# @!parse extend ClassMethods
|
10
|
+
DSLS = {_attributes: {}, _serializer: nil, _key: nil, _transform_keys: nil}.freeze
|
11
|
+
private_constant :DSLS
|
12
|
+
|
13
|
+
# @private
|
10
14
|
def self.included(base)
|
11
15
|
super
|
12
16
|
base.class_eval do
|
@@ -23,16 +27,22 @@ module Alba
|
|
23
27
|
module InstanceMethods
|
24
28
|
attr_reader :object, :_key, :params
|
25
29
|
|
30
|
+
# @param object [Object] the object to be serialized
|
31
|
+
# @param params [Hash] user-given Hash for arbitrary data
|
26
32
|
def initialize(object, params: {})
|
27
33
|
@object = object
|
28
|
-
@params = params
|
34
|
+
@params = params.freeze
|
29
35
|
DSLS.each_key { |name| instance_variable_set("@#{name}", self.class.public_send(name)) }
|
30
36
|
end
|
31
37
|
|
38
|
+
# Get serializer with `with` argument and serialize self with it
|
39
|
+
#
|
40
|
+
# @param with [nil, Proc, Alba::Serializer] selializer
|
41
|
+
# @return [String] serialized JSON string
|
32
42
|
def serialize(with: nil)
|
33
43
|
serializer = case with
|
34
44
|
when nil
|
35
|
-
@_serializer ||
|
45
|
+
@_serializer || empty_serializer
|
36
46
|
when ->(obj) { obj.is_a?(Class) && obj <= Alba::Serializer }
|
37
47
|
with
|
38
48
|
when Proc
|
@@ -43,36 +53,60 @@ module Alba
|
|
43
53
|
serializer.new(self).serialize
|
44
54
|
end
|
45
55
|
|
56
|
+
# A Hash for serialization
|
57
|
+
#
|
58
|
+
# @return [Hash]
|
46
59
|
def serializable_hash
|
47
60
|
collection? ? @object.map(&converter) : converter.call(@object)
|
48
61
|
end
|
49
62
|
alias to_hash serializable_hash
|
50
63
|
|
64
|
+
# @return [Symbol]
|
51
65
|
def key
|
52
66
|
@_key || self.class.name.delete_suffix('Resource').downcase.gsub(/:{2}/, '_').to_sym
|
53
67
|
end
|
54
68
|
|
55
69
|
private
|
56
70
|
|
71
|
+
# rubocop:disable Style/MethodCalledOnDoEndBlock
|
57
72
|
def converter
|
58
73
|
lambda do |resource|
|
59
|
-
@_attributes.
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
74
|
+
@_attributes.map do |key, attribute|
|
75
|
+
[transform_key(key), fetch_attribute(resource, attribute)]
|
76
|
+
end.to_h
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# rubocop:enable Style/MethodCalledOnDoEndBlock
|
80
|
+
|
81
|
+
# Override this method to supply custom key transform method
|
82
|
+
def transform_key(key)
|
83
|
+
return key unless @_transform_keys
|
84
|
+
|
85
|
+
require_relative 'key_transformer'
|
86
|
+
KeyTransformer.transform(key, @_transform_keys)
|
87
|
+
end
|
88
|
+
|
89
|
+
def fetch_attribute(resource, attribute)
|
90
|
+
case attribute
|
91
|
+
when Symbol
|
92
|
+
resource.public_send attribute
|
93
|
+
when Proc
|
94
|
+
instance_exec(resource, &attribute)
|
95
|
+
when Alba::One, Alba::Many
|
96
|
+
attribute.to_hash(resource, params: params)
|
97
|
+
else
|
98
|
+
raise ::Alba::Error, "Unsupported type of attribute: #{attribute.class}"
|
71
99
|
end
|
72
100
|
end
|
73
101
|
|
102
|
+
def empty_serializer
|
103
|
+
klass = Class.new
|
104
|
+
klass.include Alba::Serializer
|
105
|
+
klass
|
106
|
+
end
|
107
|
+
|
74
108
|
def inline_extended_serializer(with)
|
75
|
-
klass =
|
109
|
+
klass = empty_serializer
|
76
110
|
klass.class_eval(&with)
|
77
111
|
klass
|
78
112
|
end
|
@@ -86,43 +120,86 @@ module Alba
|
|
86
120
|
module ClassMethods
|
87
121
|
attr_reader(*DSLS.keys)
|
88
122
|
|
123
|
+
# @private
|
89
124
|
def inherited(subclass)
|
90
125
|
super
|
91
126
|
DSLS.each_key { |name| subclass.instance_variable_set("@#{name}", instance_variable_get("@#{name}").clone) }
|
92
127
|
end
|
93
128
|
|
129
|
+
# Set multiple attributes at once
|
130
|
+
#
|
131
|
+
# @param attrs [Array<String, Symbol>]
|
94
132
|
def attributes(*attrs)
|
95
133
|
attrs.each { |attr_name| @_attributes[attr_name.to_sym] = attr_name.to_sym }
|
96
134
|
end
|
97
135
|
|
136
|
+
# Set an attribute with the given block
|
137
|
+
#
|
138
|
+
# @param name [String, Symbol] key name
|
139
|
+
# @param block [Block] the block called during serialization
|
140
|
+
# @raise [ArgumentError] if block is absent
|
98
141
|
def attribute(name, &block)
|
99
142
|
raise ArgumentError, 'No block given in attribute method' unless block
|
100
143
|
|
101
144
|
@_attributes[name.to_sym] = block
|
102
145
|
end
|
103
146
|
|
147
|
+
# Set One association
|
148
|
+
#
|
149
|
+
# @param name [String, Symbol]
|
150
|
+
# @param condition [Proc]
|
151
|
+
# @param resource [Class<Alba::Resource>]
|
152
|
+
# @param key [String, Symbol] used as key when given
|
153
|
+
# @param block [Block]
|
154
|
+
# @see Alba::One#initialize
|
104
155
|
def one(name, condition = nil, resource: nil, key: nil, &block)
|
105
156
|
@_attributes[key&.to_sym || name.to_sym] = One.new(name: name, condition: condition, resource: resource, &block)
|
106
157
|
end
|
158
|
+
alias has_one one
|
107
159
|
|
160
|
+
# Set Many association
|
161
|
+
#
|
162
|
+
# @param name [String, Symbol]
|
163
|
+
# @param condition [Proc]
|
164
|
+
# @param resource [Class<Alba::Resource>]
|
165
|
+
# @param key [String, Symbol] used as key when given
|
166
|
+
# @param block [Block]
|
167
|
+
# @see Alba::Many#initialize
|
108
168
|
def many(name, condition = nil, resource: nil, key: nil, &block)
|
109
169
|
@_attributes[key&.to_sym || name.to_sym] = Many.new(name: name, condition: condition, resource: resource, &block)
|
110
170
|
end
|
171
|
+
alias has_many many
|
111
172
|
|
173
|
+
# Set serializer for the resource
|
174
|
+
#
|
175
|
+
# @param name [Alba::Serializer]
|
112
176
|
def serializer(name)
|
113
177
|
@_serializer = name <= Alba::Serializer ? name : nil
|
114
178
|
end
|
115
179
|
|
180
|
+
# Set key
|
181
|
+
#
|
182
|
+
# @param key [String, Symbol]
|
116
183
|
def key(key)
|
117
184
|
@_key = key.to_sym
|
118
185
|
end
|
119
186
|
|
187
|
+
# Delete attributes
|
120
188
|
# Use this DSL in child class to ignore certain attributes
|
189
|
+
#
|
190
|
+
# @param attributes [Array<String, Symbol>]
|
121
191
|
def ignoring(*attributes)
|
122
192
|
attributes.each do |attr_name|
|
123
193
|
@_attributes.delete(attr_name.to_sym)
|
124
194
|
end
|
125
195
|
end
|
196
|
+
|
197
|
+
# Transform keys as specified type
|
198
|
+
#
|
199
|
+
# @params type [String, Symbol]
|
200
|
+
def transform_keys(type)
|
201
|
+
@_transform_keys = type.to_sym
|
202
|
+
end
|
126
203
|
end
|
127
204
|
end
|
128
205
|
end
|
data/lib/alba/serializer.rb
CHANGED
@@ -1,22 +1,36 @@
|
|
1
1
|
module Alba
|
2
2
|
# This module represents how a resource should be serialized.
|
3
3
|
module Serializer
|
4
|
+
# @!parse include InstanceMethods
|
5
|
+
# @!parse extend ClassMethods
|
6
|
+
|
7
|
+
# @private
|
4
8
|
def self.included(base)
|
5
9
|
super
|
10
|
+
base.class_eval do
|
11
|
+
@_opts = {} unless instance_variable_defined?('@_opts')
|
12
|
+
@_metadata = {} unless instance_variable_defined?('@_metadata')
|
13
|
+
end
|
6
14
|
base.include InstanceMethods
|
7
15
|
base.extend ClassMethods
|
8
16
|
end
|
9
17
|
|
10
18
|
# Instance methods
|
11
19
|
module InstanceMethods
|
20
|
+
# @param resource [Alba::Resource]
|
12
21
|
def initialize(resource)
|
13
22
|
@resource = resource
|
14
23
|
@hash = resource.serializable_hash
|
15
24
|
@hash = {key.to_sym => @hash} if key
|
25
|
+
return if metadata.empty?
|
26
|
+
|
16
27
|
# @hash is either Hash or Array
|
17
28
|
@hash.is_a?(Hash) ? @hash.merge!(metadata.to_h) : @hash << metadata
|
18
29
|
end
|
19
30
|
|
31
|
+
# Use real encoder to actually serialize to JSON
|
32
|
+
#
|
33
|
+
# @return [String] JSON string
|
20
34
|
def serialize
|
21
35
|
Alba.encoder.call(@hash)
|
22
36
|
end
|
@@ -24,12 +38,12 @@ module Alba
|
|
24
38
|
private
|
25
39
|
|
26
40
|
def key
|
27
|
-
opts = self.class._opts
|
41
|
+
opts = self.class._opts
|
28
42
|
opts[:key] == true ? @resource.key : opts[:key]
|
29
43
|
end
|
30
44
|
|
31
45
|
def metadata
|
32
|
-
metadata = self.class._metadata
|
46
|
+
metadata = self.class._metadata
|
33
47
|
metadata.transform_values { |block| block.call(@resource.object) }
|
34
48
|
end
|
35
49
|
end
|
@@ -38,19 +52,25 @@ module Alba
|
|
38
52
|
module ClassMethods
|
39
53
|
attr_reader :_opts, :_metadata
|
40
54
|
|
55
|
+
# @private
|
41
56
|
def inherited(subclass)
|
42
57
|
super
|
43
|
-
%w[_opts _metadata].each { |name| subclass.instance_variable_set("@#{name}",
|
58
|
+
%w[_opts _metadata].each { |name| subclass.instance_variable_set("@#{name}", public_send(name).clone) }
|
44
59
|
end
|
45
60
|
|
61
|
+
# Set options, currently key only
|
62
|
+
#
|
63
|
+
# @param key [Boolean, Symbol]
|
46
64
|
def set(key: false)
|
47
|
-
@_opts ||= {}
|
48
65
|
@_opts[:key] = key
|
49
66
|
end
|
50
67
|
|
68
|
+
# Set metadata
|
69
|
+
#
|
70
|
+
# @param name [String, Symbol] key for the metadata
|
71
|
+
# @param block [Block] the content of the metadata
|
51
72
|
def metadata(name, &block)
|
52
|
-
@_metadata
|
53
|
-
@_metadata[name] = block
|
73
|
+
@_metadata[name.to_sym] = block
|
54
74
|
end
|
55
75
|
end
|
56
76
|
end
|
data/lib/alba/version.rb
CHANGED
data/sider.yml
CHANGED
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: 0.
|
4
|
+
version: 0.13.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:
|
11
|
+
date: 2021-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Alba is designed to be a simple, easy to use and fast alternative to
|
14
14
|
existing JSON serializers. Its performance is better than almost all gems which
|
@@ -22,6 +22,7 @@ files:
|
|
22
22
|
- ".gitignore"
|
23
23
|
- ".rubocop.yml"
|
24
24
|
- ".travis.yml"
|
25
|
+
- ".yardopts"
|
25
26
|
- CODE_OF_CONDUCT.md
|
26
27
|
- Gemfile
|
27
28
|
- Gemfile.lock
|
@@ -33,12 +34,11 @@ files:
|
|
33
34
|
- bin/setup
|
34
35
|
- lib/alba.rb
|
35
36
|
- lib/alba/association.rb
|
37
|
+
- lib/alba/key_transformer.rb
|
36
38
|
- lib/alba/many.rb
|
37
39
|
- lib/alba/one.rb
|
38
40
|
- lib/alba/resource.rb
|
39
|
-
- lib/alba/resources/default_resource.rb
|
40
41
|
- lib/alba/serializer.rb
|
41
|
-
- lib/alba/serializers/default_serializer.rb
|
42
42
|
- lib/alba/version.rb
|
43
43
|
- sider.yml
|
44
44
|
homepage: https://github.com/okuramasafumi/alba
|
@@ -56,14 +56,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
57
57
|
- - ">="
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: 2.5.
|
59
|
+
version: 2.5.7
|
60
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
64
|
version: '0'
|
65
65
|
requirements: []
|
66
|
-
rubygems_version: 3.
|
66
|
+
rubygems_version: 3.0.3
|
67
67
|
signing_key:
|
68
68
|
specification_version: 4
|
69
69
|
summary: Alba is the fastest JSON serializer for Ruby.
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'alba/serializer'
|
2
|
-
|
3
|
-
module Alba
|
4
|
-
module Serializers
|
5
|
-
# DefaultSerializer class is used when a user doesn't specify serializer opt.
|
6
|
-
# It's basically an alias of Alba::Serializer, but since it's a module this class simply include it.
|
7
|
-
class DefaultSerializer
|
8
|
-
include Alba::Serializer
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|