alba 0.13.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,10 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
+ ENV["BUNDLE_GEMFILE"] = File.expand_path("gemfiles/all.gemfile") if ENV["BUNDLE_GEMFILE"] == File.expand_path("Gemfile") || ENV["BUNDLE_GEMFILE"].empty? || ENV["BUNDLE_GEMFILE"].nil?
5
+
4
6
  Rake::TestTask.new(:test) do |t|
5
7
  t.libs << "test"
6
8
  t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
9
+ file_list = ENV["BUNDLE_GEMFILE"] == File.expand_path("gemfiles/all.gemfile") ? FileList["test/**/*_test.rb"] : FileList["test/dependencies/test_dependencies.rb"]
10
+ t.test_files = file_list
8
11
  end
9
12
 
10
13
  task :default => :test
data/SECURITY.md ADDED
@@ -0,0 +1,12 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ | ------- | ------------------ |
7
+ | 1.x.y | :white_check_mark: |
8
+ | < 1.0 | :x: |
9
+
10
+ ## Reporting a Vulnerability
11
+
12
+ If you find a vulnerability of Alba, please contact me (OKURA Masafumi) via [email](masafumi.o1988@gmail.com). I'll report back within a few days.
data/alba.gemspec CHANGED
@@ -7,14 +7,14 @@ Gem::Specification.new do |spec|
7
7
  spec.email = ['masafumi.o1988@gmail.com']
8
8
 
9
9
  spec.summary = 'Alba is the fastest JSON serializer for Ruby.'
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."
10
+ spec.description = "Alba is the fastest JSON serializer for Ruby. It focuses on performance, flexibility and usability."
11
11
  spec.homepage = 'https://github.com/okuramasafumi/alba'
12
12
  spec.license = 'MIT'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5.7')
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
14
14
 
15
15
  spec.metadata['homepage_uri'] = spec.homepage
16
16
  spec.metadata['source_code_uri'] = 'https://github.com/okuramasafumi/alba'
17
- spec.metadata['changelog_uri'] = 'https://github.com/okuramasafumi/alba/CHANGELOG.md'
17
+ spec.metadata['changelog_uri'] = 'https://github.com/okuramasafumi/alba/blob/master/CHANGELOG.md'
18
18
 
19
19
  # Specify which files should be added to the gem when it is released.
20
20
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -0,0 +1,392 @@
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 "jsonapi-serializer" # successor of fast_jsonapi
20
+ gem "multi_json"
21
+ gem "primalize"
22
+ gem "oj"
23
+ gem "representable"
24
+ gem "simple_ams"
25
+ gem "sqlite3"
26
+ end
27
+
28
+ # --- Test data model setup ---
29
+
30
+ require "active_record"
31
+ require "logger"
32
+ require "oj"
33
+ require "sqlite3"
34
+ Oj.optimize_rails
35
+
36
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
37
+ # ActiveRecord::Base.logger = Logger.new($stdout)
38
+
39
+ ActiveRecord::Schema.define do
40
+ create_table :posts, force: true do |t|
41
+ t.string :body
42
+ end
43
+
44
+ create_table :comments, force: true do |t|
45
+ t.integer :post_id
46
+ t.string :body
47
+ t.integer :commenter_id
48
+ end
49
+
50
+ create_table :users, force: true do |t|
51
+ t.string :name
52
+ end
53
+ end
54
+
55
+ class Post < ActiveRecord::Base
56
+ has_many :comments
57
+ has_many :commenters, through: :comments, class_name: 'User', source: :commenter
58
+
59
+ def attributes
60
+ {id: nil, body: nil, commenter_names: commenter_names}
61
+ end
62
+
63
+ def commenter_names
64
+ commenters.pluck(:name)
65
+ end
66
+ end
67
+
68
+ class Comment < ActiveRecord::Base
69
+ belongs_to :post
70
+ belongs_to :commenter, class_name: 'User'
71
+
72
+ def attributes
73
+ {id: nil, body: nil}
74
+ end
75
+ end
76
+
77
+ class User < ActiveRecord::Base
78
+ has_many :comments
79
+ end
80
+
81
+ # --- Alba serializers ---
82
+
83
+ require "alba"
84
+
85
+ class AlbaCommentResource
86
+ include ::Alba::Resource
87
+ attributes :id, :body
88
+ end
89
+
90
+ class AlbaPostResource
91
+ include ::Alba::Resource
92
+ attributes :id, :body
93
+ attribute :commenter_names do |post|
94
+ post.commenters.pluck(:name)
95
+ end
96
+ many :comments, resource: AlbaCommentResource
97
+ end
98
+
99
+ # --- ActiveModelSerializer serializers ---
100
+
101
+ require "active_model_serializers"
102
+
103
+ ActiveModelSerializers.logger = Logger.new(nil)
104
+
105
+ class AMSCommentSerializer < ActiveModel::Serializer
106
+ attributes :id, :body
107
+ end
108
+
109
+ class AMSPostSerializer < ActiveModel::Serializer
110
+ attributes :id, :body
111
+ attribute :commenter_names
112
+ has_many :comments, serializer: AMSCommentSerializer
113
+
114
+ def commenter_names
115
+ object.commenters.pluck(:name)
116
+ end
117
+ end
118
+
119
+ # --- Blueprint serializers ---
120
+
121
+ require "blueprinter"
122
+
123
+ class CommentBlueprint < Blueprinter::Base
124
+ fields :id, :body
125
+ end
126
+
127
+ class PostBlueprint < Blueprinter::Base
128
+ fields :id, :body, :commenter_names
129
+ association :comments, blueprint: CommentBlueprint
130
+
131
+ def commenter_names
132
+ commenters.pluck(:name)
133
+ end
134
+ end
135
+
136
+ # --- JBuilder serializers ---
137
+
138
+ require "jbuilder"
139
+
140
+ class Post
141
+ def to_builder
142
+ Jbuilder.new do |post|
143
+ post.call(self, :id, :body, :commenter_names, :comments)
144
+ end
145
+ end
146
+
147
+ def commenter_names
148
+ commenters.pluck(:name)
149
+ end
150
+ end
151
+
152
+ class Comment
153
+ def to_builder
154
+ Jbuilder.new do |comment|
155
+ comment.call(self, :id, :body)
156
+ end
157
+ end
158
+ end
159
+
160
+ # --- JSONAPI:Serializer serializers / (successor of fast_jsonapi) ---
161
+
162
+ class JsonApiStandardCommentSerializer
163
+ include JSONAPI::Serializer
164
+
165
+ attribute :id
166
+ attribute :body
167
+ end
168
+
169
+ class JsonApiStandardPostSerializer
170
+ include JSONAPI::Serializer
171
+
172
+ # set_type :post # optional
173
+ attribute :id
174
+ attribute :body
175
+ attribute :commenter_names
176
+
177
+ attribute :comments do |post|
178
+ post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
179
+ end
180
+ end
181
+
182
+ # --- JSONAPI:Serializer serializers that format the code the same flat way as the other gems here ---
183
+
184
+ # code to convert from JSON:API output to "flat" JSON, like the other serializers build
185
+ class JsonApiSameFormatSerializer
186
+ include JSONAPI::Serializer
187
+
188
+ def as_json(*_options)
189
+ hash = serializable_hash
190
+
191
+ if hash[:data].is_a? Hash
192
+ hash[:data][:attributes]
193
+
194
+ elsif hash[:data].is_a? Array
195
+ hash[:data].pluck(:attributes)
196
+
197
+ elsif hash[:data].nil?
198
+ { }
199
+
200
+ else
201
+ raise "unexpected data type #{hash[:data].class}"
202
+ end
203
+ end
204
+ end
205
+
206
+ class JsonApiSameFormatCommentSerializer < JsonApiSameFormatSerializer
207
+ attribute :id
208
+ attribute :body
209
+ end
210
+
211
+ class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
212
+ attribute :id
213
+ attribute :body
214
+ attribute :commenter_names
215
+
216
+ attribute :comments do |post|
217
+ post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
218
+ end
219
+ end
220
+
221
+ # --- Primalize serializers ---
222
+ #
223
+ class PrimalizeCommentResource < Primalize::Single
224
+ attributes id: integer, body: string
225
+ end
226
+
227
+ class PrimalizePostResource < Primalize::Single
228
+ alias post object
229
+
230
+ attributes(
231
+ id: integer,
232
+ body: string,
233
+ comments: array(primalize(PrimalizeCommentResource)),
234
+ commenter_names: array(string),
235
+ )
236
+
237
+ def commenter_names
238
+ post.commenters.pluck(:name)
239
+ end
240
+ end
241
+
242
+ class PrimalizePostsResource < Primalize::Many
243
+ attributes posts: enumerable(PrimalizePostResource)
244
+ end
245
+
246
+ # --- Representable serializers ---
247
+
248
+ require "representable"
249
+
250
+ class CommentRepresenter < Representable::Decorator
251
+ include Representable::JSON
252
+
253
+ property :id
254
+ property :body
255
+ end
256
+
257
+ class PostsRepresenter < Representable::Decorator
258
+ include Representable::JSON::Collection
259
+
260
+ items class: Post do
261
+ property :id
262
+ property :body
263
+ property :commenter_names
264
+ collection :comments
265
+ end
266
+
267
+ def commenter_names
268
+ commenters.pluck(:name)
269
+ end
270
+ end
271
+
272
+ # --- SimpleAMS serializers ---
273
+
274
+ require "simple_ams"
275
+
276
+ class SimpleAMSCommentSerializer
277
+ include SimpleAMS::DSL
278
+
279
+ attributes :id, :body
280
+ end
281
+
282
+ class SimpleAMSPostSerializer
283
+ include SimpleAMS::DSL
284
+
285
+ attributes :id, :body
286
+ attribute :commenter_names
287
+ has_many :comments, serializer: SimpleAMSCommentSerializer
288
+
289
+ def commenter_names
290
+ object.commenters.pluck(:name)
291
+ end
292
+ end
293
+
294
+ # --- Test data creation ---
295
+
296
+ 100.times do |i|
297
+ post = Post.create!(body: "post#{i}")
298
+ user1 = User.create!(name: "John#{i}")
299
+ user2 = User.create!(name: "Jane#{i}")
300
+ 10.times do |n|
301
+ post.comments.create!(commenter: user1, body: "Comment1_#{i}_#{n}")
302
+ post.comments.create!(commenter: user2, body: "Comment2_#{i}_#{n}")
303
+ end
304
+ end
305
+
306
+ posts = Post.all.to_a
307
+
308
+ # --- Store the serializers in procs ---
309
+
310
+ alba = Proc.new { AlbaPostResource.new(posts).serialize }
311
+ alba_inline = Proc.new do
312
+ Alba.serialize(posts) do
313
+ attributes :id, :body
314
+ attribute :commenter_names do |post|
315
+ post.commenters.pluck(:name)
316
+ end
317
+ many :comments do
318
+ attributes :id, :body
319
+ end
320
+ end
321
+ end
322
+ ams = Proc.new { ActiveModelSerializers::SerializableResource.new(posts, {}).as_json }
323
+ blueprinter = Proc.new { PostBlueprint.render(posts) }
324
+ jbuilder = Proc.new do
325
+ Jbuilder.new do |json|
326
+ json.array!(posts) do |post|
327
+ json.post post.to_builder
328
+ end
329
+ end.target!
330
+ end
331
+ jsonapi = proc { JsonApiStandardPostSerializer.new(posts).to_json }
332
+ jsonapi_same_format = proc { JsonApiSameFormatPostSerializer.new(posts).to_json }
333
+ primalize = proc { PrimalizePostsResource.new(posts: posts).to_json }
334
+ rails = Proc.new do
335
+ ActiveSupport::JSON.encode(posts.map{ |post| post.serializable_hash(include: :comments) })
336
+ end
337
+ representable = Proc.new { PostsRepresenter.new(posts).to_json }
338
+ simple_ams = Proc.new { SimpleAMS::Renderer::Collection.new(posts, serializer: SimpleAMSPostSerializer).to_json }
339
+
340
+ # --- Execute the serializers to check their output ---
341
+
342
+ puts "Serializer outputs ----------------------------------"
343
+ {
344
+ alba: alba,
345
+ alba_inline: alba_inline,
346
+ ams: ams,
347
+ blueprinter: blueprinter,
348
+ jbuilder: jbuilder, # different order
349
+ jsonapi: jsonapi, # nested JSON:API format
350
+ jsonapi_same_format: jsonapi_same_format,
351
+ primalize: primalize,
352
+ rails: rails,
353
+ representable: representable,
354
+ simple_ams: simple_ams,
355
+ }.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }
356
+
357
+ # --- Run the benchmarks ---
358
+
359
+ require 'benchmark/ips'
360
+ Benchmark.ips do |x|
361
+ x.report(:alba, &alba)
362
+ x.report(:alba_inline, &alba_inline)
363
+ x.report(:ams, &ams)
364
+ x.report(:blueprinter, &blueprinter)
365
+ x.report(:jbuilder, &jbuilder)
366
+ x.report(:jsonapi, &jsonapi)
367
+ x.report(:jsonapi_same_format, &jsonapi_same_format)
368
+ x.report(:primalize, &primalize)
369
+ x.report(:rails, &rails)
370
+ x.report(:representable, &representable)
371
+ x.report(:simple_ams, &simple_ams)
372
+
373
+ x.compare!
374
+ end
375
+
376
+
377
+ require 'benchmark/memory'
378
+ Benchmark.memory do |x|
379
+ x.report(:alba, &alba)
380
+ x.report(:alba_inline, &alba_inline)
381
+ x.report(:ams, &ams)
382
+ x.report(:blueprinter, &blueprinter)
383
+ x.report(:jbuilder, &jbuilder)
384
+ x.report(:jsonapi, &jsonapi)
385
+ x.report(:jsonapi_same_format, &jsonapi_same_format)
386
+ x.report(:primalize, &primalize)
387
+ x.report(:rails, &rails)
388
+ x.report(:representable, &representable)
389
+ x.report(:simple_ams, &simple_ams)
390
+
391
+ x.compare!
392
+ end
@@ -0,0 +1,370 @@
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 "blueprinter"
17
+ gem "jbuilder"
18
+ gem "jsonapi-serializer" # successor of fast_jsonapi
19
+ gem "multi_json"
20
+ gem "primalize"
21
+ gem "oj"
22
+ gem "representable"
23
+ gem "simple_ams"
24
+ gem "sqlite3"
25
+ end
26
+
27
+ # --- Test data model setup ---
28
+
29
+ require "active_record"
30
+ require "logger"
31
+ require "oj"
32
+ require "sqlite3"
33
+ Oj.optimize_rails
34
+
35
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
36
+ # ActiveRecord::Base.logger = Logger.new($stdout)
37
+
38
+ ActiveRecord::Schema.define do
39
+ create_table :posts, force: true do |t|
40
+ t.string :body
41
+ end
42
+
43
+ create_table :comments, force: true do |t|
44
+ t.integer :post_id
45
+ t.string :body
46
+ t.integer :commenter_id
47
+ end
48
+
49
+ create_table :users, force: true do |t|
50
+ t.string :name
51
+ end
52
+ end
53
+
54
+ class Post < ActiveRecord::Base
55
+ has_many :comments
56
+ has_many :commenters, through: :comments, class_name: 'User', source: :commenter
57
+
58
+ def attributes
59
+ {id: nil, body: nil, commenter_names: commenter_names}
60
+ end
61
+
62
+ def commenter_names
63
+ commenters.pluck(:name)
64
+ end
65
+ end
66
+
67
+ class Comment < ActiveRecord::Base
68
+ belongs_to :post
69
+ belongs_to :commenter, class_name: 'User'
70
+
71
+ def attributes
72
+ {id: nil, body: nil}
73
+ end
74
+ end
75
+
76
+ class User < ActiveRecord::Base
77
+ has_many :comments
78
+ end
79
+
80
+ # --- Alba serializers ---
81
+
82
+ require "alba"
83
+
84
+ class AlbaCommentResource
85
+ include ::Alba::Resource
86
+ attributes :id, :body
87
+ end
88
+
89
+ class AlbaPostResource
90
+ include ::Alba::Resource
91
+ attributes :id, :body
92
+ attribute :commenter_names do |post|
93
+ post.commenters.pluck(:name)
94
+ end
95
+ many :comments, resource: AlbaCommentResource
96
+ end
97
+
98
+ # --- ActiveModelSerializer serializers ---
99
+
100
+ require "active_model_serializers"
101
+
102
+ class AMSCommentSerializer < ActiveModel::Serializer
103
+ attributes :id, :body
104
+ end
105
+
106
+ class AMSPostSerializer < ActiveModel::Serializer
107
+ attributes :id, :body
108
+ attribute :commenter_names
109
+ has_many :comments, serializer: AMSCommentSerializer
110
+
111
+ def commenter_names
112
+ object.commenters.pluck(:name)
113
+ end
114
+ end
115
+
116
+ # --- Blueprint serializers ---
117
+
118
+ require "blueprinter"
119
+
120
+ class CommentBlueprint < Blueprinter::Base
121
+ fields :id, :body
122
+ end
123
+
124
+ class PostBlueprint < Blueprinter::Base
125
+ fields :id, :body, :commenter_names
126
+ association :comments, blueprint: CommentBlueprint
127
+
128
+ def commenter_names
129
+ commenters.pluck(:name)
130
+ end
131
+ end
132
+
133
+ # --- JBuilder serializers ---
134
+
135
+ require "jbuilder"
136
+
137
+ class Post
138
+ def to_builder
139
+ Jbuilder.new do |post|
140
+ post.call(self, :id, :body, :commenter_names, :comments)
141
+ end
142
+ end
143
+
144
+ def commenter_names
145
+ commenters.pluck(:name)
146
+ end
147
+ end
148
+
149
+ class Comment
150
+ def to_builder
151
+ Jbuilder.new do |comment|
152
+ comment.call(self, :id, :body)
153
+ end
154
+ end
155
+ end
156
+
157
+ # --- JSONAPI:Serializer serializers / (successor of fast_jsonapi) ---
158
+
159
+ class JsonApiStandardCommentSerializer
160
+ include JSONAPI::Serializer
161
+
162
+ attribute :id
163
+ attribute :body
164
+ end
165
+
166
+ class JsonApiStandardPostSerializer
167
+ include JSONAPI::Serializer
168
+
169
+ # set_type :post # optional
170
+ attribute :id
171
+ attribute :body
172
+ attribute :commenter_names
173
+
174
+ attribute :comments do |post|
175
+ post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
176
+ end
177
+ end
178
+
179
+ # --- JSONAPI:Serializer serializers that format the code the same flat way as the other gems here ---
180
+
181
+ # code to convert from JSON:API output to "flat" JSON, like the other serializers build
182
+ class JsonApiSameFormatSerializer
183
+ include JSONAPI::Serializer
184
+
185
+ def as_json(*_options)
186
+ hash = serializable_hash
187
+
188
+ if hash[:data].is_a? Hash
189
+ hash[:data][:attributes]
190
+
191
+ elsif hash[:data].is_a? Array
192
+ hash[:data].pluck(:attributes)
193
+
194
+ elsif hash[:data].nil?
195
+ { }
196
+
197
+ else
198
+ raise "unexpected data type #{hash[:data].class}"
199
+ end
200
+ end
201
+ end
202
+
203
+ class JsonApiSameFormatCommentSerializer < JsonApiSameFormatSerializer
204
+ attribute :id
205
+ attribute :body
206
+ end
207
+
208
+ class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
209
+ attribute :id
210
+ attribute :body
211
+ attribute :commenter_names
212
+
213
+ attribute :comments do |post|
214
+ post.comments.map { |comment| JsonApiSameFormatCommentSerializer.new(comment) }
215
+ end
216
+ end
217
+
218
+ # --- Primalize serializers ---
219
+ #
220
+ class PrimalizeCommentResource < Primalize::Single
221
+ attributes id: integer, body: string
222
+ end
223
+
224
+ class PrimalizePostResource < Primalize::Single
225
+ alias post object
226
+
227
+ attributes(
228
+ id: integer,
229
+ body: string,
230
+ comments: array(primalize(PrimalizeCommentResource)),
231
+ commenter_names: array(string),
232
+ )
233
+
234
+ def commenter_names
235
+ post.commenters.pluck(:name)
236
+ end
237
+ end
238
+
239
+ # --- Representable serializers ---
240
+
241
+ require "representable"
242
+
243
+ class CommentRepresenter < Representable::Decorator
244
+ include Representable::JSON
245
+
246
+ property :id
247
+ property :body
248
+ end
249
+
250
+ class PostRepresenter < Representable::Decorator
251
+ include Representable::JSON
252
+
253
+ property :id
254
+ property :body
255
+ property :commenter_names
256
+ collection :comments
257
+
258
+ def commenter_names
259
+ commenters.pluck(:name)
260
+ end
261
+ end
262
+
263
+ # --- SimpleAMS serializers ---
264
+
265
+ require "simple_ams"
266
+
267
+ class SimpleAMSCommentSerializer
268
+ include SimpleAMS::DSL
269
+
270
+ attributes :id, :body
271
+ end
272
+
273
+ class SimpleAMSPostSerializer
274
+ include SimpleAMS::DSL
275
+
276
+ attributes :id, :body
277
+ attribute :commenter_names
278
+ has_many :comments, serializer: SimpleAMSCommentSerializer
279
+
280
+ def commenter_names
281
+ object.commenters.pluck(:name)
282
+ end
283
+ end
284
+
285
+ # --- Test data creation ---
286
+
287
+ post = Post.create!(body: 'post')
288
+ user1 = User.create!(name: 'John')
289
+ user2 = User.create!(name: 'Jane')
290
+ post.comments.create!(commenter: user1, body: 'Comment1')
291
+ post.comments.create!(commenter: user2, body: 'Comment2')
292
+ post.reload
293
+
294
+ # --- Store the serializers in procs ---
295
+
296
+ alba = Proc.new { AlbaPostResource.new(post).serialize }
297
+ alba_inline = Proc.new do
298
+ Alba.serialize(post) do
299
+ attributes :id, :body
300
+ attribute :commenter_names do |post|
301
+ post.commenters.pluck(:name)
302
+ end
303
+ many :comments do
304
+ attributes :id, :body
305
+ end
306
+ end
307
+ end
308
+ ams = Proc.new { AMSPostSerializer.new(post, {}).to_json }
309
+ blueprinter = Proc.new { PostBlueprint.render(post) }
310
+ jbuilder = Proc.new { post.to_builder.target! }
311
+ jsonapi = proc { JsonApiStandardPostSerializer.new(post).to_json }
312
+ jsonapi_same_format = proc { JsonApiSameFormatPostSerializer.new(post).to_json }
313
+ primalize = proc { PrimalizePostResource.new(post).to_json }
314
+ rails = Proc.new { ActiveSupport::JSON.encode(post.serializable_hash(include: :comments)) }
315
+ representable = Proc.new { PostRepresenter.new(post).to_json }
316
+ simple_ams = Proc.new { SimpleAMS::Renderer.new(post, serializer: SimpleAMSPostSerializer).to_json }
317
+
318
+ # --- Execute the serializers to check their output ---
319
+
320
+ puts "Serializer outputs ----------------------------------"
321
+ {
322
+ alba: alba,
323
+ alba_inline: alba_inline,
324
+ ams: ams,
325
+ blueprinter: blueprinter,
326
+ jbuilder: jbuilder, # different order
327
+ jsonapi: jsonapi, # nested JSON:API format
328
+ jsonapi_same_format: jsonapi_same_format,
329
+ primalize: primalize,
330
+ rails: rails,
331
+ representable: representable,
332
+ simple_ams: simple_ams,
333
+ }.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }
334
+
335
+ # --- Run the benchmarks ---
336
+
337
+ require 'benchmark/ips'
338
+ Benchmark.ips do |x|
339
+ x.report(:alba, &alba)
340
+ x.report(:alba_inline, &alba_inline)
341
+ x.report(:ams, &ams)
342
+ x.report(:blueprinter, &blueprinter)
343
+ x.report(:jbuilder, &jbuilder)
344
+ x.report(:jsonapi, &jsonapi)
345
+ x.report(:jsonapi_same_format, &jsonapi_same_format)
346
+ x.report(:primalize, &primalize)
347
+ x.report(:rails, &rails)
348
+ x.report(:representable, &representable)
349
+ x.report(:simple_ams, &simple_ams)
350
+
351
+ x.compare!
352
+ end
353
+
354
+
355
+ require 'benchmark/memory'
356
+ Benchmark.memory do |x|
357
+ x.report(:alba, &alba)
358
+ x.report(:alba_inline, &alba_inline)
359
+ x.report(:ams, &ams)
360
+ x.report(:blueprinter, &blueprinter)
361
+ x.report(:jbuilder, &jbuilder)
362
+ x.report(:jsonapi, &jsonapi)
363
+ x.report(:jsonapi_same_format, &jsonapi_same_format)
364
+ x.report(:primalize, &primalize)
365
+ x.report(:rails, &rails)
366
+ x.report(:representable, &representable)
367
+ x.report(:simple_ams, &simple_ams)
368
+
369
+ x.compare!
370
+ end