alba 0.13.0 → 0.13.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +25 -0
- data/.rubocop.yml +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -11
- data/README.md +42 -3
- data/benchmark/local.rb +198 -0
- data/lib/alba/key_transformer.rb +1 -1
- data/lib/alba/many.rb +2 -0
- data/lib/alba/one.rb +2 -0
- data/lib/alba/resource.rb +1 -1
- data/lib/alba/serializer.rb +2 -4
- data/lib/alba/version.rb +1 -1
- metadata +5 -4
- data/.travis.yml +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 993f4b887c19f4e1149ddb850cd07a8cb8c2042cde0fb3974b1380537707a55d
|
4
|
+
data.tar.gz: acf77a0aa35f7fe23fc3f98843064d2800e0b4e0739e587dd29aab65f06269ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b8e52dcaf4ca33cba0685c2a0a06c16df69cd04b6d399c092e920548f5baa6a21aeab8097f90e92ab35ac9c260d83858c19462a9ec2a689d97c6999daef5e3a
|
7
|
+
data.tar.gz: e525a66c30477cab6741436128398a6f0309a0f786040fe946a9f2783d08f619df00d85157d04c5876cc579e19cceabf22dcb3556addf6ad061d44d1f0cfa888
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on: [push,pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
strategy:
|
8
|
+
fail-fast: false
|
9
|
+
matrix:
|
10
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
11
|
+
ruby: [2.5, 2.6, 2.7, 3.0, head, truffleruby]
|
12
|
+
exclude:
|
13
|
+
- os: windows-latest
|
14
|
+
ruby: truffleruby
|
15
|
+
runs-on: ${{ matrix.os }}
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v2
|
18
|
+
- name: Set up Ruby
|
19
|
+
uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
bundler-cache: true
|
23
|
+
- name: Run the default task
|
24
|
+
run: |
|
25
|
+
bundle exec rake
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
@@ -10,7 +10,7 @@ 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
12
|
gem 'rubocop-minitest', '~> 0.10.3', require: false # For lint
|
13
|
-
gem 'rubocop-performance', '~> 1.
|
13
|
+
gem 'rubocop-performance', '~> 1.10.1', require: false # For lint
|
14
14
|
gem 'rubocop-rake', '>= 0.5.1', require: false # For lint
|
15
15
|
gem 'rubocop-sensible', '~> 0.3.0', require: false # For lint
|
16
16
|
gem 'yard', require: false
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
alba (0.13.
|
4
|
+
alba (0.13.1)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
activesupport (6.1.
|
9
|
+
activesupport (6.1.3)
|
10
10
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
11
|
i18n (>= 1.6, < 2)
|
12
12
|
minitest (>= 5.1)
|
13
13
|
tzinfo (~> 2.0)
|
14
14
|
zeitwerk (~> 2.3)
|
15
|
-
ast (2.4.
|
16
|
-
concurrent-ruby (1.1.
|
15
|
+
ast (2.4.2)
|
16
|
+
concurrent-ruby (1.1.8)
|
17
17
|
coveralls (0.8.23)
|
18
18
|
json (>= 1.8, < 3)
|
19
19
|
simplecov (~> 0.16.1)
|
@@ -21,19 +21,19 @@ GEM
|
|
21
21
|
thor (>= 0.19.4, < 2.0)
|
22
22
|
tins (~> 1.6)
|
23
23
|
docile (1.3.2)
|
24
|
-
i18n (1.8.
|
24
|
+
i18n (1.8.9)
|
25
25
|
concurrent-ruby (~> 1.0)
|
26
26
|
json (2.3.1)
|
27
27
|
minitest (5.14.3)
|
28
|
-
oj (3.11.
|
28
|
+
oj (3.11.2)
|
29
29
|
parallel (1.20.1)
|
30
30
|
parser (3.0.0.0)
|
31
31
|
ast (~> 2.4.1)
|
32
32
|
rainbow (3.0.0)
|
33
33
|
rake (13.0.3)
|
34
|
-
regexp_parser (2.
|
34
|
+
regexp_parser (2.1.1)
|
35
35
|
rexml (3.2.4)
|
36
|
-
rubocop (1.
|
36
|
+
rubocop (1.11.0)
|
37
37
|
parallel (~> 1.10)
|
38
38
|
parser (>= 3.0.0.0)
|
39
39
|
rainbow (>= 2.2.2, < 4.0)
|
@@ -42,11 +42,11 @@ GEM
|
|
42
42
|
rubocop-ast (>= 1.2.0, < 2.0)
|
43
43
|
ruby-progressbar (~> 1.7)
|
44
44
|
unicode-display_width (>= 1.4.0, < 3.0)
|
45
|
-
rubocop-ast (1.4.
|
45
|
+
rubocop-ast (1.4.1)
|
46
46
|
parser (>= 2.7.1.5)
|
47
47
|
rubocop-minitest (0.10.3)
|
48
48
|
rubocop (>= 0.87, < 2.0)
|
49
|
-
rubocop-performance (1.
|
49
|
+
rubocop-performance (1.10.1)
|
50
50
|
rubocop (>= 0.90.0, < 2.0)
|
51
51
|
rubocop-ast (>= 0.4.0)
|
52
52
|
rubocop-rake (0.5.1)
|
@@ -83,7 +83,7 @@ DEPENDENCIES
|
|
83
83
|
rake (~> 13.0)
|
84
84
|
rubocop (>= 0.79.0)
|
85
85
|
rubocop-minitest (~> 0.10.3)
|
86
|
-
rubocop-performance (~> 1.
|
86
|
+
rubocop-performance (~> 1.10.1)
|
87
87
|
rubocop-rake (>= 0.5.1)
|
88
88
|
rubocop-sensible (~> 0.3.0)
|
89
89
|
yard
|
data/README.md
CHANGED
@@ -19,11 +19,11 @@ Alba has some advantages over other JSON serializers which we've wanted to have.
|
|
19
19
|
|
20
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.
|
21
21
|
|
22
|
-
Alba is also understandable internally. The codebase is much smaller than the alternatives. In fact, it's
|
22
|
+
Alba is also understandable internally. The codebase is much smaller than the alternatives. In fact, it's about 330 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!
|
23
23
|
|
24
24
|
### Performance
|
25
25
|
|
26
|
-
Alba is faster than most of the alternatives. We have a [benchmark](https://
|
26
|
+
Alba is faster than most of the alternatives. We have a [benchmark](https://github.com/okuramasafumi/alba/tree/master/benchmark).
|
27
27
|
|
28
28
|
## Installation
|
29
29
|
|
@@ -47,7 +47,7 @@ Alba supports CRuby 2.5.7 and higher and latest TruffleRuby.
|
|
47
47
|
|
48
48
|
## Documentation
|
49
49
|
|
50
|
-
You can find the documentation on [RubyDoc](https://rubydoc.info/
|
50
|
+
You can find the documentation on [RubyDoc](https://rubydoc.info/github/okuramasafumi/alba).
|
51
51
|
|
52
52
|
## Features
|
53
53
|
|
@@ -59,6 +59,7 @@ You can find the documentation on [RubyDoc](https://rubydoc.info/gems/alba).
|
|
59
59
|
* Setting root key separately in Serializer
|
60
60
|
* Adding metadata
|
61
61
|
* Selectable backend
|
62
|
+
* Key transformation
|
62
63
|
* No runtime dependencies
|
63
64
|
|
64
65
|
## Anti features
|
@@ -253,6 +254,44 @@ UserResourceCamel.new(user).serialize
|
|
253
254
|
|
254
255
|
Supported transformation types are :camel, :lower_camel and :dash.
|
255
256
|
|
257
|
+
### Filtering attributes
|
258
|
+
|
259
|
+
You can filter attributes by overriding `Alba::Resource#converter` method, but it's a bit tricky.
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
class User
|
263
|
+
attr_accessor :id, :name, :email, :created_at, :updated_at
|
264
|
+
|
265
|
+
def initialize(id, name, email)
|
266
|
+
@id = id
|
267
|
+
@name = name
|
268
|
+
@email = email
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
class UserResource
|
273
|
+
include Alba::Resource
|
274
|
+
|
275
|
+
attributes :id, :name, :email
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
# Here using `Proc#>>` method to compose a proc from `super`
|
280
|
+
def converter
|
281
|
+
super >> proc { |hash| hash.compact }
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
user = User.new(1, nil, nil)
|
286
|
+
UserResource.new(user).serialize # => '{"id":1}'
|
287
|
+
|
288
|
+
|
289
|
+
```
|
290
|
+
|
291
|
+
The key part is the use of `Proc#>>` since `Alba::Resource#converter` returns a `Proc` which contains the basic logic and it's impossible to change its behavior by just overriding the method.
|
292
|
+
|
293
|
+
It's not recommended to swap the whole conversion logic. It's recommended to always call `super` when you override `converter`.
|
294
|
+
|
256
295
|
## Comparison
|
257
296
|
|
258
297
|
Alba is faster than alternatives.
|
data/benchmark/local.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
# Benchmark script to run varieties of JSON serializers
|
2
|
+
# Fetch Alba from local, otherwise fetch latest from RubyGems
|
3
|
+
|
4
|
+
require "bundler/inline"
|
5
|
+
|
6
|
+
gemfile(true) do
|
7
|
+
source "https://rubygems.org"
|
8
|
+
|
9
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
10
|
+
|
11
|
+
gem "activerecord", "6.1.3"
|
12
|
+
gem "sqlite3"
|
13
|
+
gem "jbuilder"
|
14
|
+
gem "active_model_serializers"
|
15
|
+
gem "blueprinter"
|
16
|
+
gem "representable"
|
17
|
+
gem "alba", path: '../'
|
18
|
+
gem "oj"
|
19
|
+
gem "multi_json"
|
20
|
+
end
|
21
|
+
|
22
|
+
require "active_record"
|
23
|
+
require "sqlite3"
|
24
|
+
require "logger"
|
25
|
+
require "oj"
|
26
|
+
Oj.optimize_rails
|
27
|
+
|
28
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
29
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
30
|
+
|
31
|
+
ActiveRecord::Schema.define do
|
32
|
+
create_table :posts, force: true do |t|
|
33
|
+
t.string :body
|
34
|
+
end
|
35
|
+
|
36
|
+
create_table :comments, force: true do |t|
|
37
|
+
t.integer :post_id
|
38
|
+
t.string :body
|
39
|
+
t.integer :commenter_id
|
40
|
+
end
|
41
|
+
|
42
|
+
create_table :users, force: true do |t|
|
43
|
+
t.string :name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Post < ActiveRecord::Base
|
48
|
+
has_many :comments
|
49
|
+
has_many :commenters, through: :comments, class_name: 'User', source: :commenter
|
50
|
+
|
51
|
+
def attributes
|
52
|
+
{id: nil, body: nil, commenter_names: commenter_names}
|
53
|
+
end
|
54
|
+
|
55
|
+
def commenter_names
|
56
|
+
commenters.pluck(:name)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Comment < ActiveRecord::Base
|
61
|
+
belongs_to :post
|
62
|
+
belongs_to :commenter, class_name: 'User'
|
63
|
+
|
64
|
+
def attributes
|
65
|
+
{id: nil, body: nil}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class User < ActiveRecord::Base
|
70
|
+
has_many :comments
|
71
|
+
end
|
72
|
+
|
73
|
+
require "alba"
|
74
|
+
Alba.backend = :oj
|
75
|
+
|
76
|
+
class AlbaCommentResource
|
77
|
+
include ::Alba::Resource
|
78
|
+
attributes :id, :body
|
79
|
+
end
|
80
|
+
|
81
|
+
class AlbaPostResource
|
82
|
+
include ::Alba::Resource
|
83
|
+
attributes :id, :body
|
84
|
+
many :comments, resource: AlbaCommentResource
|
85
|
+
attribute :commenter_names do |post|
|
86
|
+
post.commenters.pluck(:name)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
require "jbuilder"
|
91
|
+
class Post
|
92
|
+
def to_builder
|
93
|
+
Jbuilder.new do |post|
|
94
|
+
post.call(self, :id, :body, :comments, :commenter_names)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def commenter_names
|
99
|
+
commenters.pluck(:name)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Comment
|
104
|
+
def to_builder
|
105
|
+
Jbuilder.new do |comment|
|
106
|
+
comment.call(self, :id, :body)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
require "active_model_serializers"
|
112
|
+
|
113
|
+
class AMSCommentSerializer < ActiveModel::Serializer
|
114
|
+
attributes :id, :body
|
115
|
+
end
|
116
|
+
|
117
|
+
class AMSPostSerializer < ActiveModel::Serializer
|
118
|
+
attributes :id, :body
|
119
|
+
has_many :comments, serializer: AMSCommentSerializer
|
120
|
+
attribute :commenter_names
|
121
|
+
def commenter_names
|
122
|
+
object.commenters.pluck(:name)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
require "blueprinter"
|
127
|
+
|
128
|
+
class CommentBlueprint < Blueprinter::Base
|
129
|
+
fields :id, :body
|
130
|
+
end
|
131
|
+
|
132
|
+
class PostBlueprint < Blueprinter::Base
|
133
|
+
fields :id, :body, :commenter_names
|
134
|
+
association :comments, blueprint: CommentBlueprint
|
135
|
+
def commenter_names
|
136
|
+
commenters.pluck(:name)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
require "representable"
|
141
|
+
|
142
|
+
class CommentRepresenter < Representable::Decorator
|
143
|
+
include Representable::JSON
|
144
|
+
|
145
|
+
property :id
|
146
|
+
property :body
|
147
|
+
end
|
148
|
+
|
149
|
+
class PostRepresenter < Representable::Decorator
|
150
|
+
include Representable::JSON
|
151
|
+
|
152
|
+
property :id
|
153
|
+
property :body
|
154
|
+
property :commenter_names
|
155
|
+
collection :comments
|
156
|
+
|
157
|
+
def commenter_names
|
158
|
+
commenters.pluck(:name)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
post = Post.create!(body: 'post')
|
163
|
+
user1 = User.create!(name: 'John')
|
164
|
+
user2 = User.create!(name: 'Jane')
|
165
|
+
post.comments.create!(commenter: user1, body: 'Comment1')
|
166
|
+
post.comments.create!(commenter: user2, body: 'Comment2')
|
167
|
+
post.reload
|
168
|
+
|
169
|
+
alba = Proc.new { AlbaPostResource.new(post).serialize }
|
170
|
+
jbuilder = Proc.new { post.to_builder.target! }
|
171
|
+
ams = Proc.new { AMSPostSerializer.new(post, {}).to_json }
|
172
|
+
rails = Proc.new { ActiveSupport::JSON.encode(post.serializable_hash(include: :comments)) }
|
173
|
+
blueprinter = Proc.new { PostBlueprint.render(post) }
|
174
|
+
representable = Proc.new { PostRepresenter.new(post).to_json }
|
175
|
+
alba_inline = Proc.new do
|
176
|
+
Alba.serialize(post) do
|
177
|
+
attributes :id, :body
|
178
|
+
attribute :commenter_names do |post|
|
179
|
+
post.commenters.pluck(:name)
|
180
|
+
end
|
181
|
+
many :comments do
|
182
|
+
attributes :id, :body
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
[alba, jbuilder, ams, rails, blueprinter, representable, alba_inline].each {|x| puts x.call }
|
187
|
+
|
188
|
+
require 'benchmark'
|
189
|
+
time = 1000
|
190
|
+
Benchmark.bmbm do |x|
|
191
|
+
x.report(:alba) { time.times(&alba) }
|
192
|
+
x.report(:jbuilder) { time.times(&jbuilder) }
|
193
|
+
x.report(:ams) { time.times(&ams) }
|
194
|
+
x.report(:rails) { time.times(&rails) }
|
195
|
+
x.report(:blueprinter) { time.times(&blueprinter) }
|
196
|
+
x.report(:representable) { time.times(&representable) }
|
197
|
+
x.report(:alba_inline) { time.times(&alba_inline) }
|
198
|
+
end
|
data/lib/alba/key_transformer.rb
CHANGED
@@ -24,7 +24,7 @@ module Alba
|
|
24
24
|
when :dash
|
25
25
|
ActiveSupport::Inflector.dasherize(key)
|
26
26
|
else
|
27
|
-
raise ::Alba::Error, "Unknown transform_type: #{transform_type}. Supported transform_type are :camel and :dash."
|
27
|
+
raise ::Alba::Error, "Unknown transform_type: #{transform_type}. Supported transform_type are :camel, :lower_camel and :dash."
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
data/lib/alba/many.rb
CHANGED
data/lib/alba/one.rb
CHANGED
data/lib/alba/resource.rb
CHANGED
data/lib/alba/serializer.rb
CHANGED
@@ -7,10 +7,8 @@ module Alba
|
|
7
7
|
# @private
|
8
8
|
def self.included(base)
|
9
9
|
super
|
10
|
-
base.
|
11
|
-
|
12
|
-
@_metadata = {} unless instance_variable_defined?('@_metadata')
|
13
|
-
end
|
10
|
+
base.instance_variable_set('@_opts', {}) unless base.instance_variable_defined?('@_opts')
|
11
|
+
base.instance_variable_set('@_metadata', {}) unless base.instance_variable_defined?('@_metadata')
|
14
12
|
base.include InstanceMethods
|
15
13
|
base.extend ClassMethods
|
16
14
|
end
|
data/lib/alba/version.rb
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.13.
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OKURA Masafumi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-24 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
|
@@ -19,9 +19,9 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- ".github/workflows/main.yml"
|
22
23
|
- ".gitignore"
|
23
24
|
- ".rubocop.yml"
|
24
|
-
- ".travis.yml"
|
25
25
|
- ".yardopts"
|
26
26
|
- CODE_OF_CONDUCT.md
|
27
27
|
- Gemfile
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- README.md
|
31
31
|
- Rakefile
|
32
32
|
- alba.gemspec
|
33
|
+
- benchmark/local.rb
|
33
34
|
- bin/console
|
34
35
|
- bin/setup
|
35
36
|
- lib/alba.rb
|
@@ -63,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
64
|
- !ruby/object:Gem::Version
|
64
65
|
version: '0'
|
65
66
|
requirements: []
|
66
|
-
rubygems_version: 3.
|
67
|
+
rubygems_version: 3.2.11
|
67
68
|
signing_key:
|
68
69
|
specification_version: 4
|
69
70
|
summary: Alba is the fastest JSON serializer for Ruby.
|