alba 1.1.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +26 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/dependabot.yml +26 -0
- data/.github/workflows/perf.yml +21 -0
- data/.rubocop.yml +18 -8
- data/.yardopts +2 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +4 -3
- data/README.md +377 -14
- data/SECURITY.md +12 -0
- data/alba.gemspec +2 -2
- data/benchmark/collection.rb +441 -0
- data/benchmark/{local.rb → single_resource.rb} +120 -15
- data/codecov.yml +3 -0
- data/docs/migrate_from_active_model_serializers.md +359 -0
- data/docs/migrate_from_jbuilder.md +223 -0
- data/gemfiles/all.gemfile +1 -1
- data/gemfiles/without_active_support.gemfile +1 -1
- data/gemfiles/without_oj.gemfile +1 -1
- data/lib/alba/association.rb +14 -17
- data/lib/alba/default_inflector.rb +36 -0
- data/lib/alba/deprecation.rb +14 -0
- data/lib/alba/key_transform_factory.rb +33 -0
- data/lib/alba/many.rb +1 -1
- data/lib/alba/resource.rb +226 -83
- data/lib/alba/typed_attribute.rb +61 -0
- data/lib/alba/version.rb +1 -1
- data/lib/alba.rb +82 -21
- data/script/perf_check.rb +174 -0
- data/sider.yml +2 -4
- metadata +20 -9
- data/lib/alba/key_transformer.rb +0 -32
@@ -0,0 +1,441 @@
|
|
1
|
+
# Benchmark script to run varieties of JSON serializers
|
2
|
+
# Fetch Alba from local, otherwise fetch latest from RubyGems
|
3
|
+
|
4
|
+
# --- Bundle dependencies ---
|
5
|
+
|
6
|
+
require "bundler/inline"
|
7
|
+
|
8
|
+
gemfile(true) do
|
9
|
+
source "https://rubygems.org"
|
10
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
11
|
+
|
12
|
+
gem "active_model_serializers"
|
13
|
+
gem "activerecord", "6.1.3"
|
14
|
+
gem "alba", path: '../'
|
15
|
+
gem "benchmark-ips"
|
16
|
+
gem "benchmark-memory"
|
17
|
+
gem "blueprinter"
|
18
|
+
gem "jbuilder"
|
19
|
+
gem "jserializer"
|
20
|
+
gem "jsonapi-serializer" # successor of fast_jsonapi
|
21
|
+
gem "multi_json"
|
22
|
+
gem "panko_serializer"
|
23
|
+
gem "pg"
|
24
|
+
gem "primalize"
|
25
|
+
gem "oj"
|
26
|
+
gem "representable"
|
27
|
+
gem "simple_ams"
|
28
|
+
gem "sqlite3"
|
29
|
+
end
|
30
|
+
|
31
|
+
# --- Test data model setup ---
|
32
|
+
|
33
|
+
require "pg"
|
34
|
+
require "active_record"
|
35
|
+
require "active_record/connection_adapters/postgresql_adapter"
|
36
|
+
require "logger"
|
37
|
+
require "oj"
|
38
|
+
require "sqlite3"
|
39
|
+
Oj.optimize_rails
|
40
|
+
|
41
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
42
|
+
# ActiveRecord::Base.logger = Logger.new($stdout)
|
43
|
+
|
44
|
+
ActiveRecord::Schema.define do
|
45
|
+
create_table :posts, force: true do |t|
|
46
|
+
t.string :body
|
47
|
+
end
|
48
|
+
|
49
|
+
create_table :comments, force: true do |t|
|
50
|
+
t.integer :post_id
|
51
|
+
t.string :body
|
52
|
+
t.integer :commenter_id
|
53
|
+
end
|
54
|
+
|
55
|
+
create_table :users, force: true do |t|
|
56
|
+
t.string :name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Post < ActiveRecord::Base
|
61
|
+
has_many :comments
|
62
|
+
has_many :commenters, through: :comments, class_name: 'User', source: :commenter
|
63
|
+
|
64
|
+
def attributes
|
65
|
+
{id: nil, body: nil, commenter_names: commenter_names}
|
66
|
+
end
|
67
|
+
|
68
|
+
def commenter_names
|
69
|
+
commenters.pluck(:name)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Comment < ActiveRecord::Base
|
74
|
+
belongs_to :post
|
75
|
+
belongs_to :commenter, class_name: 'User'
|
76
|
+
|
77
|
+
def attributes
|
78
|
+
{id: nil, body: nil}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class User < ActiveRecord::Base
|
83
|
+
has_many :comments
|
84
|
+
end
|
85
|
+
|
86
|
+
# --- Alba serializers ---
|
87
|
+
|
88
|
+
require "alba"
|
89
|
+
|
90
|
+
class AlbaCommentResource
|
91
|
+
include ::Alba::Resource
|
92
|
+
attributes :id, :body
|
93
|
+
end
|
94
|
+
|
95
|
+
class AlbaPostResource
|
96
|
+
include ::Alba::Resource
|
97
|
+
attributes :id, :body
|
98
|
+
attribute :commenter_names do |post|
|
99
|
+
post.commenters.pluck(:name)
|
100
|
+
end
|
101
|
+
many :comments, resource: AlbaCommentResource
|
102
|
+
end
|
103
|
+
|
104
|
+
# --- ActiveModelSerializer serializers ---
|
105
|
+
|
106
|
+
require "active_model_serializers"
|
107
|
+
|
108
|
+
ActiveModelSerializers.logger = Logger.new(nil)
|
109
|
+
|
110
|
+
class AMSCommentSerializer < ActiveModel::Serializer
|
111
|
+
attributes :id, :body
|
112
|
+
end
|
113
|
+
|
114
|
+
class AMSPostSerializer < ActiveModel::Serializer
|
115
|
+
attributes :id, :body
|
116
|
+
attribute :commenter_names
|
117
|
+
has_many :comments, serializer: AMSCommentSerializer
|
118
|
+
|
119
|
+
def commenter_names
|
120
|
+
object.commenters.pluck(:name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# --- Blueprint serializers ---
|
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
|
+
|
136
|
+
def commenter_names
|
137
|
+
commenters.pluck(:name)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# --- JBuilder serializers ---
|
142
|
+
|
143
|
+
require "jbuilder"
|
144
|
+
|
145
|
+
class Post
|
146
|
+
def to_builder
|
147
|
+
Jbuilder.new do |post|
|
148
|
+
post.call(self, :id, :body, :commenter_names, :comments)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def commenter_names
|
153
|
+
commenters.pluck(:name)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
class Comment
|
158
|
+
def to_builder
|
159
|
+
Jbuilder.new do |comment|
|
160
|
+
comment.call(self, :id, :body)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# --- Jserializer serializers ---
|
166
|
+
|
167
|
+
require 'jserializer'
|
168
|
+
|
169
|
+
class JserializerCommentSerializer < Jserializer::Base
|
170
|
+
attributes :id, :body
|
171
|
+
end
|
172
|
+
|
173
|
+
class JserializerPostSerializer < Jserializer::Base
|
174
|
+
attributes :id, :body, :commenter_names
|
175
|
+
has_many :comments, serializer: JserializerCommentSerializer
|
176
|
+
def commenter_names
|
177
|
+
object.commenters.pluck(:name)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# --- JSONAPI:Serializer serializers / (successor of fast_jsonapi) ---
|
182
|
+
|
183
|
+
class JsonApiStandardCommentSerializer
|
184
|
+
include JSONAPI::Serializer
|
185
|
+
|
186
|
+
attribute :id
|
187
|
+
attribute :body
|
188
|
+
end
|
189
|
+
|
190
|
+
class JsonApiStandardPostSerializer
|
191
|
+
include JSONAPI::Serializer
|
192
|
+
|
193
|
+
# set_type :post # optional
|
194
|
+
attribute :id
|
195
|
+
attribute :body
|
196
|
+
attribute :commenter_names
|
197
|
+
|
198
|
+
attribute :comments do |post|
|
199
|
+
post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# --- JSONAPI:Serializer serializers that format the code the same flat way as the other gems here ---
|
204
|
+
|
205
|
+
# code to convert from JSON:API output to "flat" JSON, like the other serializers build
|
206
|
+
class JsonApiSameFormatSerializer
|
207
|
+
include JSONAPI::Serializer
|
208
|
+
|
209
|
+
def as_json(*_options)
|
210
|
+
hash = serializable_hash
|
211
|
+
|
212
|
+
if hash[:data].is_a? Hash
|
213
|
+
hash[:data][:attributes]
|
214
|
+
|
215
|
+
elsif hash[:data].is_a? Array
|
216
|
+
hash[:data].pluck(:attributes)
|
217
|
+
|
218
|
+
elsif hash[:data].nil?
|
219
|
+
{ }
|
220
|
+
|
221
|
+
else
|
222
|
+
raise "unexpected data type #{hash[:data].class}"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class JsonApiSameFormatCommentSerializer < JsonApiSameFormatSerializer
|
228
|
+
attribute :id
|
229
|
+
attribute :body
|
230
|
+
end
|
231
|
+
|
232
|
+
class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
|
233
|
+
attribute :id
|
234
|
+
attribute :body
|
235
|
+
attribute :commenter_names
|
236
|
+
|
237
|
+
attribute :comments do |post|
|
238
|
+
post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# --- Panko serializers ---
|
243
|
+
#
|
244
|
+
|
245
|
+
require "panko_serializer"
|
246
|
+
|
247
|
+
class PankoCommentSerializer < Panko::Serializer
|
248
|
+
attributes :id, :body
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
class PankoPostSerializer < Panko::Serializer
|
253
|
+
attributes :id, :body, :commenter_names
|
254
|
+
|
255
|
+
has_many :comments, serializer: PankoCommentSerializer
|
256
|
+
|
257
|
+
def commenter_names
|
258
|
+
object.comments.pluck(:name)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# --- Primalize serializers ---
|
263
|
+
#
|
264
|
+
class PrimalizeCommentResource < Primalize::Single
|
265
|
+
attributes id: integer, body: string
|
266
|
+
end
|
267
|
+
|
268
|
+
class PrimalizePostResource < Primalize::Single
|
269
|
+
alias post object
|
270
|
+
|
271
|
+
attributes(
|
272
|
+
id: integer,
|
273
|
+
body: string,
|
274
|
+
comments: array(primalize(PrimalizeCommentResource)),
|
275
|
+
commenter_names: array(string),
|
276
|
+
)
|
277
|
+
|
278
|
+
def commenter_names
|
279
|
+
post.commenters.pluck(:name)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class PrimalizePostsResource < Primalize::Many
|
284
|
+
attributes posts: enumerable(PrimalizePostResource)
|
285
|
+
end
|
286
|
+
|
287
|
+
# --- Representable serializers ---
|
288
|
+
|
289
|
+
require "representable"
|
290
|
+
|
291
|
+
class CommentRepresenter < Representable::Decorator
|
292
|
+
include Representable::JSON
|
293
|
+
|
294
|
+
property :id
|
295
|
+
property :body
|
296
|
+
end
|
297
|
+
|
298
|
+
class PostsRepresenter < Representable::Decorator
|
299
|
+
include Representable::JSON::Collection
|
300
|
+
|
301
|
+
items class: Post do
|
302
|
+
property :id
|
303
|
+
property :body
|
304
|
+
property :commenter_names
|
305
|
+
collection :comments
|
306
|
+
end
|
307
|
+
|
308
|
+
def commenter_names
|
309
|
+
commenters.pluck(:name)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# --- SimpleAMS serializers ---
|
314
|
+
|
315
|
+
require "simple_ams"
|
316
|
+
|
317
|
+
class SimpleAMSCommentSerializer
|
318
|
+
include SimpleAMS::DSL
|
319
|
+
|
320
|
+
attributes :id, :body
|
321
|
+
end
|
322
|
+
|
323
|
+
class SimpleAMSPostSerializer
|
324
|
+
include SimpleAMS::DSL
|
325
|
+
|
326
|
+
attributes :id, :body
|
327
|
+
attribute :commenter_names
|
328
|
+
has_many :comments, serializer: SimpleAMSCommentSerializer
|
329
|
+
|
330
|
+
def commenter_names
|
331
|
+
object.commenters.pluck(:name)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
# --- Test data creation ---
|
336
|
+
|
337
|
+
100.times do |i|
|
338
|
+
post = Post.create!(body: "post#{i}")
|
339
|
+
user1 = User.create!(name: "John#{i}")
|
340
|
+
user2 = User.create!(name: "Jane#{i}")
|
341
|
+
10.times do |n|
|
342
|
+
post.comments.create!(commenter: user1, body: "Comment1_#{i}_#{n}")
|
343
|
+
post.comments.create!(commenter: user2, body: "Comment2_#{i}_#{n}")
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
posts = Post.all.to_a
|
348
|
+
|
349
|
+
# --- Store the serializers in procs ---
|
350
|
+
|
351
|
+
alba = Proc.new { AlbaPostResource.new(posts).serialize }
|
352
|
+
alba_inline = Proc.new do
|
353
|
+
Alba.serialize(posts) do
|
354
|
+
attributes :id, :body
|
355
|
+
attribute :commenter_names do |post|
|
356
|
+
post.commenters.pluck(:name)
|
357
|
+
end
|
358
|
+
many :comments do
|
359
|
+
attributes :id, :body
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|
363
|
+
ams = Proc.new { ActiveModelSerializers::SerializableResource.new(posts, {}).as_json }
|
364
|
+
blueprinter = Proc.new { PostBlueprint.render(posts) }
|
365
|
+
jbuilder = Proc.new do
|
366
|
+
Jbuilder.new do |json|
|
367
|
+
json.array!(posts) do |post|
|
368
|
+
json.post post.to_builder
|
369
|
+
end
|
370
|
+
end.target!
|
371
|
+
end
|
372
|
+
jserializer = Proc.new { JserializerPostSerializer.new(posts, is_collection: true).to_json }
|
373
|
+
jsonapi = proc { JsonApiStandardPostSerializer.new(posts).to_json }
|
374
|
+
jsonapi_same_format = proc { JsonApiSameFormatPostSerializer.new(posts).to_json }
|
375
|
+
panko = proc { Panko::ArraySerializer.new(posts, each_serializer: PankoPostSerializer).to_json }
|
376
|
+
primalize = proc { PrimalizePostsResource.new(posts: posts).to_json }
|
377
|
+
rails = Proc.new do
|
378
|
+
ActiveSupport::JSON.encode(posts.map{ |post| post.serializable_hash(include: :comments) })
|
379
|
+
end
|
380
|
+
representable = Proc.new { PostsRepresenter.new(posts).to_json }
|
381
|
+
simple_ams = Proc.new { SimpleAMS::Renderer::Collection.new(posts, serializer: SimpleAMSPostSerializer).to_json }
|
382
|
+
|
383
|
+
# --- Execute the serializers to check their output ---
|
384
|
+
|
385
|
+
puts "Serializer outputs ----------------------------------"
|
386
|
+
{
|
387
|
+
alba: alba,
|
388
|
+
alba_inline: alba_inline,
|
389
|
+
ams: ams,
|
390
|
+
blueprinter: blueprinter,
|
391
|
+
jbuilder: jbuilder, # different order
|
392
|
+
jserializer: jserializer,
|
393
|
+
jsonapi: jsonapi, # nested JSON:API format
|
394
|
+
jsonapi_same_format: jsonapi_same_format,
|
395
|
+
panko: panko,
|
396
|
+
primalize: primalize,
|
397
|
+
rails: rails,
|
398
|
+
representable: representable,
|
399
|
+
simple_ams: simple_ams,
|
400
|
+
}.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }
|
401
|
+
|
402
|
+
# --- Run the benchmarks ---
|
403
|
+
|
404
|
+
require 'benchmark/ips'
|
405
|
+
Benchmark.ips do |x|
|
406
|
+
x.report(:alba, &alba)
|
407
|
+
x.report(:alba_inline, &alba_inline)
|
408
|
+
x.report(:ams, &ams)
|
409
|
+
x.report(:blueprinter, &blueprinter)
|
410
|
+
x.report(:jbuilder, &jbuilder)
|
411
|
+
x.report(:jserializer, &jserializer)
|
412
|
+
x.report(:jsonapi, &jsonapi)
|
413
|
+
x.report(:jsonapi_same_format, &jsonapi_same_format)
|
414
|
+
x.report(:panko, &panko)
|
415
|
+
x.report(:primalize, &primalize)
|
416
|
+
x.report(:rails, &rails)
|
417
|
+
x.report(:representable, &representable)
|
418
|
+
x.report(:simple_ams, &simple_ams)
|
419
|
+
|
420
|
+
x.compare!
|
421
|
+
end
|
422
|
+
|
423
|
+
|
424
|
+
require 'benchmark/memory'
|
425
|
+
Benchmark.memory do |x|
|
426
|
+
x.report(:alba, &alba)
|
427
|
+
x.report(:alba_inline, &alba_inline)
|
428
|
+
x.report(:ams, &ams)
|
429
|
+
x.report(:blueprinter, &blueprinter)
|
430
|
+
x.report(:jbuilder, &jbuilder)
|
431
|
+
x.report(:jserializer, &jserializer)
|
432
|
+
x.report(:jsonapi, &jsonapi)
|
433
|
+
x.report(:jsonapi_same_format, &jsonapi_same_format)
|
434
|
+
x.report(:panko, &panko)
|
435
|
+
x.report(:primalize, &primalize)
|
436
|
+
x.report(:rails, &rails)
|
437
|
+
x.report(:representable, &representable)
|
438
|
+
x.report(:simple_ams, &simple_ams)
|
439
|
+
|
440
|
+
x.compare!
|
441
|
+
end
|
@@ -13,18 +13,26 @@ gemfile(true) do
|
|
13
13
|
gem "activerecord", "6.1.3"
|
14
14
|
gem "alba", path: '../'
|
15
15
|
gem "benchmark-ips"
|
16
|
+
gem "benchmark-memory"
|
16
17
|
gem "blueprinter"
|
17
18
|
gem "jbuilder"
|
19
|
+
gem "jserializer"
|
18
20
|
gem "jsonapi-serializer" # successor of fast_jsonapi
|
19
21
|
gem "multi_json"
|
22
|
+
gem "panko_serializer"
|
23
|
+
gem "pg"
|
24
|
+
gem "primalize"
|
20
25
|
gem "oj"
|
21
26
|
gem "representable"
|
27
|
+
gem "simple_ams"
|
22
28
|
gem "sqlite3"
|
23
29
|
end
|
24
30
|
|
25
31
|
# --- Test data model setup ---
|
26
32
|
|
33
|
+
require "pg"
|
27
34
|
require "active_record"
|
35
|
+
require "active_record/connection_adapters/postgresql_adapter"
|
28
36
|
require "logger"
|
29
37
|
require "oj"
|
30
38
|
require "sqlite3"
|
@@ -152,6 +160,23 @@ class Comment
|
|
152
160
|
end
|
153
161
|
end
|
154
162
|
|
163
|
+
# --- Jserializer serializers ---
|
164
|
+
|
165
|
+
require 'jserializer'
|
166
|
+
|
167
|
+
class JserializerCommentSerializer < Jserializer::Base
|
168
|
+
attributes :id, :body
|
169
|
+
end
|
170
|
+
|
171
|
+
class JserializerPostSerializer < Jserializer::Base
|
172
|
+
attributes :id, :body, :commenter_names
|
173
|
+
has_many :comments, serializer: JserializerCommentSerializer
|
174
|
+
def commenter_names
|
175
|
+
object.commenters.pluck(:name)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
155
180
|
# --- JSONAPI:Serializer serializers / (successor of fast_jsonapi) ---
|
156
181
|
|
157
182
|
class JsonApiStandardCommentSerializer
|
@@ -213,6 +238,46 @@ class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
|
|
213
238
|
end
|
214
239
|
end
|
215
240
|
|
241
|
+
# --- Panko serializers ---
|
242
|
+
#
|
243
|
+
require "panko_serializer"
|
244
|
+
|
245
|
+
class PankoCommentSerializer < Panko::Serializer
|
246
|
+
attributes :id, :body
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
class PankoPostSerializer < Panko::Serializer
|
251
|
+
attributes :id, :body, :commenter_names
|
252
|
+
|
253
|
+
has_many :comments, serializer: PankoCommentSerializer
|
254
|
+
|
255
|
+
def commenter_names
|
256
|
+
object.comments.pluck(:name)
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# --- Primalize serializers ---
|
261
|
+
#
|
262
|
+
class PrimalizeCommentResource < Primalize::Single
|
263
|
+
attributes id: integer, body: string
|
264
|
+
end
|
265
|
+
|
266
|
+
class PrimalizePostResource < Primalize::Single
|
267
|
+
alias post object
|
268
|
+
|
269
|
+
attributes(
|
270
|
+
id: integer,
|
271
|
+
body: string,
|
272
|
+
comments: array(primalize(PrimalizeCommentResource)),
|
273
|
+
commenter_names: array(string),
|
274
|
+
)
|
275
|
+
|
276
|
+
def commenter_names
|
277
|
+
post.commenters.pluck(:name)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
216
281
|
# --- Representable serializers ---
|
217
282
|
|
218
283
|
require "representable"
|
@@ -237,6 +302,28 @@ class PostRepresenter < Representable::Decorator
|
|
237
302
|
end
|
238
303
|
end
|
239
304
|
|
305
|
+
# --- SimpleAMS serializers ---
|
306
|
+
|
307
|
+
require "simple_ams"
|
308
|
+
|
309
|
+
class SimpleAMSCommentSerializer
|
310
|
+
include SimpleAMS::DSL
|
311
|
+
|
312
|
+
attributes :id, :body
|
313
|
+
end
|
314
|
+
|
315
|
+
class SimpleAMSPostSerializer
|
316
|
+
include SimpleAMS::DSL
|
317
|
+
|
318
|
+
attributes :id, :body
|
319
|
+
attribute :commenter_names
|
320
|
+
has_many :comments, serializer: SimpleAMSCommentSerializer
|
321
|
+
|
322
|
+
def commenter_names
|
323
|
+
object.commenters.pluck(:name)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
240
327
|
# --- Test data creation ---
|
241
328
|
|
242
329
|
post = Post.create!(body: 'post')
|
@@ -263,10 +350,14 @@ end
|
|
263
350
|
ams = Proc.new { AMSPostSerializer.new(post, {}).to_json }
|
264
351
|
blueprinter = Proc.new { PostBlueprint.render(post) }
|
265
352
|
jbuilder = Proc.new { post.to_builder.target! }
|
353
|
+
jserializer = Proc.new { JserializerPostSerializer.new(post).to_json }
|
266
354
|
jsonapi = proc { JsonApiStandardPostSerializer.new(post).to_json }
|
267
355
|
jsonapi_same_format = proc { JsonApiSameFormatPostSerializer.new(post).to_json }
|
356
|
+
panko = proc { PankoPostSerializer.new.serialize_to_json(post) }
|
357
|
+
primalize = proc { PrimalizePostResource.new(post).to_json }
|
268
358
|
rails = Proc.new { ActiveSupport::JSON.encode(post.serializable_hash(include: :comments)) }
|
269
359
|
representable = Proc.new { PostRepresenter.new(post).to_json }
|
360
|
+
simple_ams = Proc.new { SimpleAMS::Renderer.new(post, serializer: SimpleAMSPostSerializer).to_json }
|
270
361
|
|
271
362
|
# --- Execute the serializers to check their output ---
|
272
363
|
|
@@ -277,28 +368,18 @@ puts "Serializer outputs ----------------------------------"
|
|
277
368
|
ams: ams,
|
278
369
|
blueprinter: blueprinter,
|
279
370
|
jbuilder: jbuilder, # different order
|
371
|
+
jserializer: jserializer,
|
280
372
|
jsonapi: jsonapi, # nested JSON:API format
|
281
373
|
jsonapi_same_format: jsonapi_same_format,
|
374
|
+
panko: panko,
|
375
|
+
primalize: primalize,
|
282
376
|
rails: rails,
|
283
|
-
representable: representable
|
377
|
+
representable: representable,
|
378
|
+
simple_ams: simple_ams,
|
284
379
|
}.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }
|
285
380
|
|
286
381
|
# --- Run the benchmarks ---
|
287
382
|
|
288
|
-
require 'benchmark'
|
289
|
-
time = 1000
|
290
|
-
Benchmark.bmbm do |x|
|
291
|
-
x.report(:alba) { time.times(&alba) }
|
292
|
-
x.report(:alba_inline) { time.times(&alba_inline) }
|
293
|
-
x.report(:ams) { time.times(&ams) }
|
294
|
-
x.report(:blueprinter) { time.times(&blueprinter) }
|
295
|
-
x.report(:jbuilder) { time.times(&jbuilder) }
|
296
|
-
x.report(:jsonapi) { time.times(&jsonapi) }
|
297
|
-
x.report(:jsonapi_same_format) { time.times(&jsonapi_same_format) }
|
298
|
-
x.report(:rails) { time.times(&rails) }
|
299
|
-
x.report(:representable) { time.times(&representable) }
|
300
|
-
end
|
301
|
-
|
302
383
|
require 'benchmark/ips'
|
303
384
|
Benchmark.ips do |x|
|
304
385
|
x.report(:alba, &alba)
|
@@ -306,10 +387,34 @@ Benchmark.ips do |x|
|
|
306
387
|
x.report(:ams, &ams)
|
307
388
|
x.report(:blueprinter, &blueprinter)
|
308
389
|
x.report(:jbuilder, &jbuilder)
|
390
|
+
x.report(:jserializer, &jserializer)
|
391
|
+
x.report(:jsonapi, &jsonapi)
|
392
|
+
x.report(:jsonapi_same_format, &jsonapi_same_format)
|
393
|
+
x.report(:panko, &panko)
|
394
|
+
x.report(:primalize, &primalize)
|
395
|
+
x.report(:rails, &rails)
|
396
|
+
x.report(:representable, &representable)
|
397
|
+
x.report(:simple_ams, &simple_ams)
|
398
|
+
|
399
|
+
x.compare!
|
400
|
+
end
|
401
|
+
|
402
|
+
|
403
|
+
require 'benchmark/memory'
|
404
|
+
Benchmark.memory do |x|
|
405
|
+
x.report(:alba, &alba)
|
406
|
+
x.report(:alba_inline, &alba_inline)
|
407
|
+
x.report(:ams, &ams)
|
408
|
+
x.report(:blueprinter, &blueprinter)
|
409
|
+
x.report(:jbuilder, &jbuilder)
|
410
|
+
x.report(:jserializer, &jserializer)
|
309
411
|
x.report(:jsonapi, &jsonapi)
|
310
412
|
x.report(:jsonapi_same_format, &jsonapi_same_format)
|
413
|
+
x.report(:panko, &panko)
|
414
|
+
x.report(:primalize, &primalize)
|
311
415
|
x.report(:rails, &rails)
|
312
416
|
x.report(:representable, &representable)
|
417
|
+
x.report(:simple_ams, &simple_ams)
|
313
418
|
|
314
419
|
x.compare!
|
315
420
|
end
|