alba 2.0.1 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9018588ddacac0cf7db8dac1d23c8165665c7a93976b581d25ab51357ead7834
4
- data.tar.gz: 6bde71c65d8fb6965d46cea2769cd9a97d4f76407136e47de4392cdfa1a58333
3
+ metadata.gz: c68ec07a949642b11dfd36b3bf748249d0d725178ece9dd331e373fc2339cb8a
4
+ data.tar.gz: 7704431d69f96b88d9632c114dae90cfceae018c8372c8736c091efd2050b65a
5
5
  SHA512:
6
- metadata.gz: a7d907446dad8ff8a19814cbf27ba74bfc84a0f00fae8366f561efd5de03e1ac16d66f3b31641e8ec83b5081e6e5fc61074c5a5e47509343fade989ab65e41da
7
- data.tar.gz: d81e0055f6899698d70ab1522e71adc8ce9e22e3a8855ad2a3db8b54e551d2ea459a77bc92242bc5c7f8121d150c322f3b99f6d286fd7118f5df2f94d0dc3fdc
6
+ metadata.gz: 98ca1b6fa7c6851f3a69d6d1cb54cd782a3142fccfb33391eb08cbc093ad691496a8fdb9e93e5ce89543032a0003ab8b60022ca8bbbba81c73de249b571a3fa6
7
+ data.tar.gz: 3756fe21da92358031a722d83b7169ef81e8749ccf6430bef577dfaac7ab4a80e68c07c6e0205497e54692f74b16e66aabad390db6eda09e486a732387541630
@@ -8,7 +8,7 @@ jobs:
8
8
  fail-fast: false
9
9
  matrix:
10
10
  os: [ubuntu-latest, windows-latest, macos-latest]
11
- ruby: [2.6, 2.7, 3.0, 3.1, head, jruby, truffleruby]
11
+ ruby: [2.7, 3.0, 3.1, 3.2, head, jruby, truffleruby]
12
12
  gemfile: [all, without_active_support, without_oj]
13
13
  exclude:
14
14
  - os: windows-latest
data/.rubocop.yml CHANGED
@@ -16,7 +16,7 @@ AllCops:
16
16
  - 'script/**/*.rb'
17
17
  NewCops: enable
18
18
  EnabledByDefault: true
19
- TargetRubyVersion: 2.6
19
+ TargetRubyVersion: 2.7
20
20
 
21
21
  # Items in Gemfile is dev dependencies and we don't have to specify versions.
22
22
  Bundler/GemVersion:
@@ -58,6 +58,11 @@ Metrics/ParameterLists:
58
58
  Exclude:
59
59
  - 'test/**/*.rb'
60
60
 
61
+ # Putting extra empty line is not valuable in test
62
+ # We prefer shorter test code
63
+ Minitest/EmptyLineBeforeAssertionMethods:
64
+ Enabled: false
65
+
61
66
  # We need to eval resource code to test errors on resource classes
62
67
  Security/Eval:
63
68
  Exclude:
data/CHANGELOG.md CHANGED
@@ -6,6 +6,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.2.0] 2023-02-17
10
+
11
+ ### Added
12
+
13
+ - Rails integration to set default inflector [#298](https://github.com/okuramasafumi/alba/pull/298)
14
+
15
+ ### Fixed
16
+
17
+ - Fix cascade not working with association and inheritance [#300](https://github.com/okuramasafumi/alba/pull/300)
18
+
19
+ ### Removed
20
+
21
+ - Drop support of Ruby 2.6
22
+
23
+ ## [2.1.0] 2022-12-03
24
+
25
+ ### Added
26
+
27
+ - Add `select` method for filtering attributes [#270](https://github.com/okuramasafumi/alba/pull/270)
28
+ - Allow ConditionalAttribute with 2-arity proc to reject nil attributes [#273](https://github.com/okuramasafumi/alba/pull/273)
29
+
30
+ ### Fixed
31
+
32
+ - Add support for proc resource in one polymorphic associations [#281](https://github.com/okuramasafumi/alba/pull/281)
33
+
34
+ ### Deprecated
35
+
36
+ - Deprecate `inference` related methods in favor of a unified `inflector` interface.
37
+ Deprecated methods are: `Alba.enable_inference!`, `Alba.disable_inference!`, and `Alba.inferring`.
38
+ Use `Alba.inflector = :active_support/:dry` or `Alba.inflector = SomeInflector` to enable.
39
+ Use `Alba.inflector = nil` to disable.
40
+ Use `Alba.inflector` to check if enabled.
41
+
9
42
  ## [2.0.1] 2022-11-02
10
43
 
11
44
  ### Fix
@@ -17,9 +50,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
17
50
 
18
51
  ### Breaking changes
19
52
 
20
- - All Hash-related methods now return String key instead of Symbol key
21
- This affects all users, but you can use `deep_symbolize_keys` in Rails environment if you prefer Symbol keys
22
- Some DSLs that take key argument such as `on_nil` and `on_error`, are also affected
53
+ - All Hash-related methods now return String keys instead of Symbol keys.
54
+ This affects all users, but you can use `deep_symbolize_keys` in Rails environment if you prefer Symbol keys, or `with_indifferent_access` to support both String and Symbol keys.
55
+ Some DSLs that take key argument such as `on_nil` and `on_error`, are also affected.
23
56
  - Remove deprecated methods: `Resource#to_hash`, `Resource.ignoring`, `Alba.on_nil`, `Alba.on_error`, `Alba.enable_root_key_transformation!` and `Alba.disable_root_key_transformation!`
24
57
  - If using `transform_keys`, the default inflector is no longer set by default [d02245c8](https://github.com/okuramasafumi/alba/commit/d02245c87e9df303cb20e354a81e5457ea460bdd#diff-ecd8c835d2390b8cb89e7ff75e599f0c15cdbe18c30981d6090f4a515566686f)
25
58
  To retain this functionality in Rails, add an initializer with the following:
data/CONTRIBUTING.md CHANGED
@@ -27,4 +27,4 @@ You're more than welcomed to submit a Pull Request! You are expected to follow t
27
27
  ## Documents
28
28
 
29
29
  * [code of conduct](https://github.com/okuramasafumi/alba/blob/master/CODE_OF_CONDUCT.md) for all contributors
30
- * [hacking document](https://github.com/okuramasafumi/alba/blob/master/DESIGN.md) for those who want to know the internal of Alba
30
+ * [hacking document](https://github.com/okuramasafumi/alba/blob/main/HACKING.md) for those who want to know the internal of Alba
data/Gemfile CHANGED
@@ -6,12 +6,12 @@ gemspec
6
6
  gem 'activesupport', require: false # For backend
7
7
  gem 'dry-inflector', require: false # For inflection
8
8
  gem 'ffaker', require: false # For testing
9
- gem 'inch', require: false # For inline documents
10
9
  gem 'minitest', '~> 5.14' # For test
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-minitest', '~> 0.23.0', require: false # For lint
14
- gem 'rubocop-performance', '~> 1.15.0', require: false # For lint
13
+ gem 'rubocop-minitest', '>= 0.25.0', require: false # For lint
14
+ gem 'rubocop-performance', '>= 1.15.0', require: false # For lint
15
15
  gem 'rubocop-rake', '>= 0.5.1', require: false # For lint
16
16
  gem 'rubocop-sensible', '~> 0.3.0', require: false # For lint
17
17
  gem 'ruby-lsp', require: false # For language server
data/README.md CHANGED
@@ -23,6 +23,16 @@ If you have feature requests or interesting ideas, join us with [Ideas](https://
23
23
 
24
24
  If you want to know more about Alba, there's a [screencast](https://hanamimastery.com/episodes/21-serialization-with-alba) created by Sebastian from [Hanami Mastery](https://hanamimastery.com/). It covers basic features of Alba and how to use it in Hanami.
25
25
 
26
+ ## What users say about Alba
27
+
28
+ > Alba is a well-maintained JSON serialization engine, for Ruby, JRuby, and TruffleRuby implementations, and what I like in this gem - except of its speed, is the easiness of use, no dependencies and the fact it plays well with any Ruby application!
29
+
30
+ [Hanami Mastery by Seb Wilgosz](https://hanamimastery.com/episodes/21-serialization-with-alba)
31
+
32
+ > Alba is more feature-rich and pretty fast, too
33
+
34
+ [Gemfile of dreams by Evil Martians](https://evilmartians.com/chronicles/gemfile-of-dreams-libraries-we-use-to-build-rails-apps)
35
+
26
36
  ## Why Alba?
27
37
 
28
38
  Because it's fast, easy and feature rich!
@@ -37,7 +47,7 @@ Alba is easy to use because there are only a few methods to remember. It's also
37
47
 
38
48
  ### Feature rich
39
49
 
40
- While Alba's core is simple, it provides additional features when you need them, For example, Alba provides [a way to control circular associations](#circular-associations-control), [inferring resource classes, root key and associations](#inference) and [supports layouts](#layout).
50
+ While Alba's core is simple, it provides additional features when you need them, For example, Alba provides [a way to control circular associations](#circular-associations-control), [root key and association resource name inference](#root-key-and-association-resource-name-inference) and [supports layouts](#layout).
41
51
 
42
52
  ## Installation
43
53
 
@@ -57,7 +67,7 @@ Or install it yourself as:
57
67
 
58
68
  ## Supported Ruby versions
59
69
 
60
- Alba supports CRuby 2.5 and higher and latest JRuby and TruffleRuby.
70
+ Alba supports CRuby 2.7 and higher and latest JRuby and TruffleRuby.
61
71
 
62
72
  ## Documentation
63
73
 
@@ -68,10 +78,9 @@ You can find the documentation on [RubyDoc](https://rubydoc.info/github/okuramas
68
78
  * Conditional attributes and associations
69
79
  * Selectable backend
70
80
  * Key transformation
71
- * Root key inference
81
+ * Root key and association resource name inference
72
82
  * Error handling
73
83
  * Nil handling
74
- * Resource name inflection based on association name
75
84
  * Circular associations control
76
85
  * [Experimental] Types for validation and conversion
77
86
  * Layout
@@ -113,19 +122,33 @@ You can consider setting a backend with Symbol as a shortcut to set encoder.
113
122
 
114
123
  #### Inference configuration
115
124
 
116
- You can enable inference feature using `enable_inference!` method.
125
+ You can enable the inference feature using the `Alba.inflector = SomeInflector` API. For example, in a Rails initializer:
117
126
 
118
127
  ```ruby
119
- Alba.enable_inference!(with: :active_support)
128
+ Alba.inflector = :active_support
120
129
  ```
121
130
 
122
- You can choose which inflector Alba uses for inference. Possible value for `with` option are:
131
+ You can choose which inflector Alba uses for inference. Possible options are:
123
132
 
124
133
  - `:active_support` for `ActiveSupport::Inflector`
125
134
  - `:dry` for `Dry::Inflector`
126
- - any object which responds to some methods (see [below](#custom-inflector))
135
+ - any object which conforms to the protocol (see [below](#custom-inflector))
136
+
137
+ To disable inference, set the `inflector` to `nil`:
138
+
139
+ ```ruby
140
+ Alba.inflector = nil
141
+ ```
127
142
 
128
- For the details, see [Error handling section](#error-handling)
143
+ To check if inference is enabled etc, inspect the return value of `inflector`:
144
+
145
+ ```ruby
146
+ if Alba.inflector == nil
147
+ puts "inflector not set"
148
+ else
149
+ puts "inflector is set to #{Alba.inflector}"
150
+ end
151
+ ```
129
152
 
130
153
  ### Simple serialization with root key
131
154
 
@@ -157,7 +180,7 @@ end
157
180
 
158
181
  user = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
159
182
  UserResource.new(user).serialize
160
- # => "{\"user\":{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"}}"
183
+ # => '{"user":{"id":1,"name":"Masafumi OKURA","name_with_email":"Masafumi OKURA: masafumi@example.com"}}'
161
184
  ```
162
185
 
163
186
  You can define instance methods on resources so that you can use it as attribute name in `attributes`.
@@ -184,7 +207,7 @@ This even works with users collection.
184
207
  user1 = User.new(1, 'Masafumi OKURA', 'masafumi@example.com')
185
208
  user2 = User.new(2, 'Test User', 'test@example.com')
186
209
  UserResource.new([user1, user2]).serialize
187
- # => "{\"users\":[{\"id\":1,\"name\":\"Masafumi OKURA\",\"name_with_email\":\"Masafumi OKURA: masafumi@example.com\"},{\"id\":2,\"name\":\"Test User\",\"name_with_email\":\"Test User: test@example.com\"}]}"
210
+ # => '{"users":[{"id":1,"name":"Masafumi OKURA","name_with_email":"Masafumi OKURA: masafumi@example.com"},{"id":2,"name":"Test User","name_with_email":"Test User: test@example.com"}]}'
188
211
  ```
189
212
 
190
213
  If you have a simple case where you want to change only the name, you can use the Symbol to Proc shortcut:
@@ -210,8 +233,8 @@ class UserResource
210
233
  end
211
234
 
212
235
  user = User.new(1, 'Masa', 'test@example.com')
213
- UserResource.new(user).serialize # => "{\"name\":\"foo\"}"
214
- UserResource.new(user, params: {upcase: true}).serialize # => "{\"name\":\"FOO\"}"
236
+ UserResource.new(user).serialize # => '{"name":"Masa"}'
237
+ UserResource.new(user, params: {upcase: true}).serialize # => '{"name":"MASA"}'
215
238
  ```
216
239
 
217
240
  ### Serialization with associations
@@ -368,9 +391,11 @@ UserResource.new(user).serialize
368
391
  # => '{"id":1,"my_articles":[{"title":"Hello World!"}]}'
369
392
  ```
370
393
 
371
- You can omit resource option if you enable Alba's inference feature.
394
+ You can omit the resource option if you enable Alba's [inference](#inference-configuration) feature.
372
395
 
373
396
  ```ruby
397
+ Alba.inflector = :active_support
398
+
374
399
  class UserResource
375
400
  include Alba::Resource
376
401
 
@@ -390,7 +415,7 @@ class UserResource
390
415
 
391
416
  attributes :id
392
417
 
393
- many :articles, ->(article) { article.with_comment? ? ArticleWithCommentResource : ArticleResource }
418
+ many :articles, resource: ->(article) { article.with_comment? ? ArticleWithCommentResource : ArticleResource }
394
419
  end
395
420
  ```
396
421
 
@@ -564,13 +589,19 @@ end
564
589
  Foo = Struct.new(:bar, :baz)
565
590
  foo = Foo.new(1, 2)
566
591
  FooResource.new(foo).serialize # => '{"foo":{"bar":1}}'
567
- ExtendedFooResource.new(foo).serialize # => '{"foo":{"bar":1,"baz":2}}'
592
+ ExtendedFooResource.new(foo).serialize # => '{"foofoo":{"bar":1,"baz":2}}'
568
593
  ```
569
594
 
570
595
  In this example we add `baz` attribute and change `root_key`. This way, you can extend existing resource classes just like normal OOP. Don't forget that when your inheritance structure is too deep it'll become difficult to modify existing classes.
571
596
 
572
597
  ### Filtering attributes
573
598
 
599
+ Filtering attributes can be done in two ways - with `attributes` and `select`. They have different semantics and usage.
600
+
601
+ `select` is a new and more intuitive API, so generally it's recommended to use `select`.
602
+
603
+ #### Filtering attributes with `attributes`
604
+
574
605
  You can filter out certain attributes by overriding `attributes` instance method. This is useful when you want to customize existing resource with inheritance.
575
606
 
576
607
  You can access raw attributes via `super` call. It returns a Hash whose keys are the name of the attribute and whose values are the body. Usually you need only keys to filter out, like below.
@@ -598,19 +629,52 @@ class RestrictedFooResource < GenericFooResource
598
629
  end
599
630
  end
600
631
 
632
+ foo = Foo.new(1, 'my foo', 'body')
633
+
601
634
  RestrictedFooResource.new(foo).serialize
602
635
  # => '{"name":"my foo"}'
603
636
  ```
604
637
 
605
- ### Key transformation
638
+ #### Filtering attributes with `select`
606
639
 
607
- If you want to use `transform_keys` DSL and you already have `active_support` installed, key transformation will work out of the box, using `ActiveSupport::Inflector`. If `active_support` is not around, you have 2 possibilities:
608
- * install it
609
- * use a [custom inflector](#custom-inflector)
640
+ When you want to filter attributes based on more complex logic, you can use `select` instance method. `select` takes two parameters, the name of an attribute and the value of an attribute. If it returns false that attribute is rejected.
610
641
 
611
- With `transform_keys` DSL, you can transform attribute keys.
642
+ ```ruby
643
+ class Foo
644
+ attr_accessor :id, :name, :body
645
+
646
+ def initialize(id, name, body)
647
+ @id = id
648
+ @name = name
649
+ @body = body
650
+ end
651
+ end
652
+
653
+ class GenericFooResource
654
+ include Alba::Resource
655
+
656
+ attributes :id, :name, :body
657
+ end
658
+
659
+ class RestrictedFooResource < GenericFooResource
660
+ def select(_key, value)
661
+ !value.nil?
662
+ end
663
+ end
664
+
665
+ foo = Foo.new(1, nil, 'body')
666
+
667
+ RestrictedFooResource.new(foo).serialize
668
+ # => '{"id":1,"body":"body"}'
669
+ ```
670
+
671
+ ### Key transformation
672
+
673
+ If you have [inference](#inference-configuration) enabled, you can use the `transform_keys` DSL to transform attribute keys.
612
674
 
613
675
  ```ruby
676
+ Alba.inflector = :active_support
677
+
614
678
  class User
615
679
  attr_reader :id, :first_name, :last_name
616
680
 
@@ -646,12 +710,12 @@ Possible values for `transform_keys` argument are:
646
710
 
647
711
  You can also transform root key when:
648
712
 
649
- * `Alba.enable_inference!` is called
713
+ * `Alba.inflector` is set
650
714
  * `root_key!` is called in Resource class
651
715
  * `root` option of `transform_keys` is set to true
652
716
 
653
717
  ```ruby
654
- Alba.enable_inference!(with: :active_support) # with :dry also works
718
+ Alba.inflector = :active_support
655
719
 
656
720
  class BankAccount
657
721
  attr_reader :account_number
@@ -675,7 +739,9 @@ BankAccountResource.new(bank_account).serialize
675
739
  # => '{"bank-account":{"account-number":123456789}}'
676
740
  ```
677
741
 
678
- This behavior to transform root key will become default at version 2.
742
+ This is the default behavior from version 2.
743
+
744
+ Find more details in the [Inference configuration](#inference-configuration) section.
679
745
 
680
746
  #### Key transformation cascading
681
747
 
@@ -687,7 +753,7 @@ You can also turn it off by setting `cascade: false` option to `transform_keys`.
687
753
 
688
754
  ```ruby
689
755
  class User
690
- attr_reader :id, :first_name, :last_name
756
+ attr_reader :id, :first_name, :last_name, :bank_account
691
757
 
692
758
  def initialize(id, first_name, last_name)
693
759
  @id = id
@@ -746,7 +812,7 @@ module CustomInflector
746
812
  end
747
813
  end
748
814
 
749
- Alba.enable_inference!(with: CustomInflector)
815
+ Alba.inflector = CustomInflector
750
816
  ```
751
817
 
752
818
  ### Conditional attributes
@@ -757,7 +823,7 @@ In these cases, conditional attributes works well. We can pass `if` option to `a
757
823
 
758
824
  ```ruby
759
825
  class User
760
- attr_accessor :id, :name, :email, :created_at, :updated_at
826
+ attr_accessor :id, :name, :email
761
827
 
762
828
  def initialize(id, name, email)
763
829
  @id = id
@@ -790,12 +856,12 @@ end
790
856
 
791
857
  We believe this is clearer than using some (not implemented yet) DSL such as `default` because there are some conditions where default values should be applied (`nil`, `blank?`, `empty?` etc.)
792
858
 
793
- ### Inference
859
+ ### Root key and association resource name inference
794
860
 
795
- After `Alba.enable_inference!` called, Alba tries to infer root key and association resource name.
861
+ If [inference](#inference-configuration) is enabled, Alba tries to infer the root key and association resource names.
796
862
 
797
863
  ```ruby
798
- Alba.enable_inference!(with: :active_support) # with :dry also works
864
+ Alba.inflector = :active_support
799
865
 
800
866
  class User
801
867
  attr_reader :id
@@ -825,7 +891,7 @@ end
825
891
  class UserResource
826
892
  include Alba::Resource
827
893
 
828
- key!
894
+ root_key!
829
895
 
830
896
  attributes :id
831
897
 
@@ -843,6 +909,8 @@ This resource automatically sets its root key to either "users" or "user", depen
843
909
 
844
910
  Also, you don't have to specify which resource class to use with `many`. Alba infers it from association name.
845
911
 
912
+ Find more details in the [Inference configuration](#inference-configuration) section.
913
+
846
914
  ### Error handling
847
915
 
848
916
  You can set error handler globally or per resource using `on_error`.
@@ -934,7 +1002,7 @@ class UserResource
934
1002
  include Alba::Resource
935
1003
 
936
1004
  on_nil do |object, key|
937
- if key == age
1005
+ if key == 'age'
938
1006
  20
939
1007
  else
940
1008
  "User#{object.id}"
@@ -990,7 +1058,7 @@ class UserResourceWithoutMeta
990
1058
  attributes :id, :name
991
1059
  end
992
1060
 
993
- UserResource.new([user]).serialize(meta: {foo: :bar})
1061
+ UserResourceWithoutMeta.new([user]).serialize(meta: {foo: :bar})
994
1062
  # => '{"users":[{"id":1,"name":"Masafumi OKURA"}],"meta":{"foo":"bar"}}'
995
1063
  ```
996
1064
 
@@ -1014,7 +1082,7 @@ You can validate and convert input with types.
1014
1082
  class User
1015
1083
  attr_reader :id, :name, :age, :bio, :admin, :created_at
1016
1084
 
1017
- def initialize(id, name, age, bio = '', admin = false) # rubocop:disable Style/OptionalBooleanParameter
1085
+ def initialize(id, name, age, bio = '', admin = false)
1018
1086
  @id = id
1019
1087
  @name = name
1020
1088
  @age = age
data/alba.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
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.6.0')
13
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
14
14
 
15
15
  spec.metadata = {
16
16
  'bug_tracker_uri' => 'https://github.com/okuramasafumi/issues',
@@ -1,88 +1,7 @@
1
1
  # Benchmark script to run varieties of JSON serializers
2
2
  # Fetch Alba from local, otherwise fetch latest from RubyGems
3
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 "fast_serializer_ruby"
19
- gem "jbuilder"
20
- gem 'turbostreamer'
21
- gem "jserializer"
22
- gem "multi_json"
23
- gem "panko_serializer"
24
- gem "pg"
25
- gem "primalize"
26
- gem "oj"
27
- gem "representable"
28
- gem "simple_ams"
29
- gem "sqlite3"
30
- end
31
-
32
- # --- Test data model setup ---
33
-
34
- require "pg"
35
- require "active_record"
36
- require "active_record/connection_adapters/postgresql_adapter"
37
- require "logger"
38
- require "oj"
39
- require "sqlite3"
40
- Oj.optimize_rails
41
-
42
- ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
43
- # ActiveRecord::Base.logger = Logger.new($stdout)
44
-
45
- ActiveRecord::Schema.define do
46
- create_table :posts, force: true do |t|
47
- t.string :body
48
- end
49
-
50
- create_table :comments, force: true do |t|
51
- t.integer :post_id
52
- t.string :body
53
- t.integer :commenter_id
54
- end
55
-
56
- create_table :users, force: true do |t|
57
- t.string :name
58
- end
59
- end
60
-
61
- class Post < ActiveRecord::Base
62
- has_many :comments
63
- has_many :commenters, through: :comments, class_name: 'User', source: :commenter
64
-
65
- def attributes
66
- {id: nil, body: nil, commenter_names: commenter_names}
67
- end
68
-
69
- def commenter_names
70
- commenters.pluck(:name)
71
- end
72
- end
73
-
74
- class Comment < ActiveRecord::Base
75
- belongs_to :post
76
- belongs_to :commenter, class_name: 'User'
77
-
78
- def attributes
79
- {id: nil, body: nil}
80
- end
81
- end
82
-
83
- class User < ActiveRecord::Base
84
- has_many :comments
85
- end
4
+ require_relative 'prep'
86
5
 
87
6
  # --- Alba serializers ---
88
7
 
@@ -160,30 +79,6 @@ class FastSerializerPostResource
160
79
  has_many :comments, serializer: FastSerializerCommentResource
161
80
  end
162
81
 
163
- # --- JBuilder serializers ---
164
-
165
- require "jbuilder"
166
-
167
- class Post
168
- def to_builder
169
- Jbuilder.new do |post|
170
- post.call(self, :id, :body, :commenter_names, :comments)
171
- end
172
- end
173
-
174
- def commenter_names
175
- commenters.pluck(:name)
176
- end
177
- end
178
-
179
- class Comment
180
- def to_builder
181
- Jbuilder.new do |comment|
182
- comment.call(self, :id, :body)
183
- end
184
- end
185
- end
186
-
187
82
  # --- Jserializer serializers ---
188
83
 
189
84
  require 'jserializer'
@@ -220,31 +115,6 @@ class PankoPostSerializer < Panko::Serializer
220
115
  end
221
116
  end
222
117
 
223
- # --- Primalize serializers ---
224
- #
225
- class PrimalizeCommentResource < Primalize::Single
226
- attributes id: integer, body: string
227
- end
228
-
229
- class PrimalizePostResource < Primalize::Single
230
- alias post object
231
-
232
- attributes(
233
- id: integer,
234
- body: string,
235
- comments: array(primalize(PrimalizeCommentResource)),
236
- commenter_names: array(string),
237
- )
238
-
239
- def commenter_names
240
- post.commenters.pluck(:name)
241
- end
242
- end
243
-
244
- class PrimalizePostsResource < Primalize::Many
245
- attributes posts: enumerable(PrimalizePostResource)
246
- end
247
-
248
118
  # --- Representable serializers ---
249
119
 
250
120
  require "representable"
@@ -349,13 +219,6 @@ end
349
219
  ams = Proc.new { ActiveModelSerializers::SerializableResource.new(posts, {each_serializer: AMSPostSerializer}).to_json }
350
220
  blueprinter = Proc.new { PostBlueprint.render(posts) }
351
221
  fast_serializer = Proc.new { FastSerializerPostResource.new(posts).to_json }
352
- jbuilder = Proc.new do
353
- Jbuilder.new do |json|
354
- json.array!(posts) do |post|
355
- json.post post.to_builder
356
- end
357
- end.target!
358
- end
359
222
  jserializer = Proc.new { JserializerPostSerializer.new(posts, is_collection: true).to_json }
360
223
  panko = proc { Panko::ArraySerializer.new(posts, each_serializer: PankoPostSerializer).to_json }
361
224
  primalize = proc { PrimalizePostsResource.new(posts: posts).to_json }
@@ -368,22 +231,25 @@ turbostreamer = Proc.new { TurbostreamerSerializer.new(posts).to_json }
368
231
 
369
232
  # --- Execute the serializers to check their output ---
370
233
  GC.disable
371
- puts "Serializer outputs ----------------------------------"
234
+ puts "Checking outputs..."
235
+ correct = alba.call
236
+ parsed_correct = JSON.parse(correct)
372
237
  {
373
- alba: alba,
374
238
  alba_inline: alba_inline,
375
239
  ams: ams,
376
240
  blueprinter: blueprinter,
377
241
  fast_serializer: fast_serializer,
378
- jbuilder: jbuilder, # different order
379
242
  jserializer: jserializer,
380
243
  panko: panko,
381
- primalize: primalize,
382
244
  rails: rails,
383
245
  representable: representable,
384
246
  simple_ams: simple_ams,
385
247
  turbostreamer: turbostreamer
386
- }.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }
248
+ }.each do |name, serializer|
249
+ result = serializer.call
250
+ parsed_result = JSON.parse(result)
251
+ puts "#{name} yields wrong output: #{parsed_result}" unless parsed_result == parsed_correct
252
+ end
387
253
 
388
254
  # --- Run the benchmarks ---
389
255
 
@@ -394,10 +260,8 @@ Benchmark.ips do |x|
394
260
  x.report(:ams, &ams)
395
261
  x.report(:blueprinter, &blueprinter)
396
262
  x.report(:fast_serializer, &fast_serializer)
397
- x.report(:jbuilder, &jbuilder)
398
263
  x.report(:jserializer, &jserializer)
399
264
  x.report(:panko, &panko)
400
- x.report(:primalize, &primalize)
401
265
  x.report(:rails, &rails)
402
266
  x.report(:representable, &representable)
403
267
  x.report(:simple_ams, &simple_ams)
@@ -414,10 +278,8 @@ Benchmark.memory do |x|
414
278
  x.report(:ams, &ams)
415
279
  x.report(:blueprinter, &blueprinter)
416
280
  x.report(:fast_serializer, &fast_serializer)
417
- x.report(:jbuilder, &jbuilder)
418
281
  x.report(:jserializer, &jserializer)
419
282
  x.report(:panko, &panko)
420
- x.report(:primalize, &primalize)
421
283
  x.report(:rails, &rails)
422
284
  x.report(:representable, &representable)
423
285
  x.report(:simple_ams, &simple_ams)