active_model_serializers_custom 0.10.90

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.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +35 -0
  5. data/.rubocop.yml +109 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +63 -0
  8. data/CHANGELOG.md +727 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +74 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +305 -0
  14. data/Rakefile +76 -0
  15. data/active_model_serializers.gemspec +64 -0
  16. data/appveyor.yml +28 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/rubocop +38 -0
  20. data/bin/serve_benchmark +39 -0
  21. data/docs/README.md +41 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +269 -0
  24. data/docs/general/caching.md +58 -0
  25. data/docs/general/configuration_options.md +185 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/fields.md +31 -0
  28. data/docs/general/getting_started.md +133 -0
  29. data/docs/general/instrumentation.md +40 -0
  30. data/docs/general/key_transforms.md +40 -0
  31. data/docs/general/logging.md +21 -0
  32. data/docs/general/rendering.md +293 -0
  33. data/docs/general/serializers.md +495 -0
  34. data/docs/how-open-source-maintained.jpg +0 -0
  35. data/docs/howto/add_pagination_links.md +138 -0
  36. data/docs/howto/add_relationship_links.md +140 -0
  37. data/docs/howto/add_root_key.md +62 -0
  38. data/docs/howto/grape_integration.md +42 -0
  39. data/docs/howto/outside_controller_use.md +66 -0
  40. data/docs/howto/passing_arbitrary_options.md +27 -0
  41. data/docs/howto/serialize_poro.md +73 -0
  42. data/docs/howto/test.md +154 -0
  43. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  44. data/docs/integrations/ember-and-json-api.md +147 -0
  45. data/docs/integrations/grape.md +19 -0
  46. data/docs/jsonapi/errors.md +56 -0
  47. data/docs/jsonapi/schema.md +151 -0
  48. data/docs/jsonapi/schema/schema.json +366 -0
  49. data/docs/rfcs/0000-namespace.md +106 -0
  50. data/docs/rfcs/template.md +15 -0
  51. data/lib/action_controller/serialization.rb +76 -0
  52. data/lib/active_model/serializable_resource.rb +13 -0
  53. data/lib/active_model/serializer.rb +418 -0
  54. data/lib/active_model/serializer/adapter.rb +26 -0
  55. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  56. data/lib/active_model/serializer/adapter/base.rb +20 -0
  57. data/lib/active_model/serializer/adapter/json.rb +17 -0
  58. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  59. data/lib/active_model/serializer/adapter/null.rb +17 -0
  60. data/lib/active_model/serializer/array_serializer.rb +14 -0
  61. data/lib/active_model/serializer/association.rb +91 -0
  62. data/lib/active_model/serializer/attribute.rb +27 -0
  63. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +90 -0
  65. data/lib/active_model/serializer/concerns/caching.rb +304 -0
  66. data/lib/active_model/serializer/error_serializer.rb +16 -0
  67. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  68. data/lib/active_model/serializer/field.rb +92 -0
  69. data/lib/active_model/serializer/fieldset.rb +33 -0
  70. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  71. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  72. data/lib/active_model/serializer/lazy_association.rb +99 -0
  73. data/lib/active_model/serializer/link.rb +23 -0
  74. data/lib/active_model/serializer/lint.rb +152 -0
  75. data/lib/active_model/serializer/null.rb +19 -0
  76. data/lib/active_model/serializer/reflection.rb +212 -0
  77. data/lib/active_model/serializer/version.rb +7 -0
  78. data/lib/active_model_serializers.rb +63 -0
  79. data/lib/active_model_serializers/adapter.rb +100 -0
  80. data/lib/active_model_serializers/adapter/attributes.rb +15 -0
  81. data/lib/active_model_serializers/adapter/base.rb +85 -0
  82. data/lib/active_model_serializers/adapter/json.rb +23 -0
  83. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  92. data/lib/active_model_serializers/adapter/null.rb +11 -0
  93. data/lib/active_model_serializers/callbacks.rb +57 -0
  94. data/lib/active_model_serializers/deprecate.rb +56 -0
  95. data/lib/active_model_serializers/deserialization.rb +17 -0
  96. data/lib/active_model_serializers/json_pointer.rb +16 -0
  97. data/lib/active_model_serializers/logging.rb +124 -0
  98. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  99. data/lib/active_model_serializers/model.rb +132 -0
  100. data/lib/active_model_serializers/railtie.rb +52 -0
  101. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  102. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  103. data/lib/active_model_serializers/serialization_context.rb +41 -0
  104. data/lib/active_model_serializers/test.rb +9 -0
  105. data/lib/active_model_serializers/test/schema.rb +140 -0
  106. data/lib/active_model_serializers/test/serializer.rb +127 -0
  107. data/lib/generators/rails/USAGE +6 -0
  108. data/lib/generators/rails/resource_override.rb +12 -0
  109. data/lib/generators/rails/serializer_generator.rb +38 -0
  110. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  111. data/lib/grape/active_model_serializers.rb +18 -0
  112. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  113. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  114. data/lib/tasks/rubocop.rake +55 -0
  115. data/test/action_controller/adapter_selector_test.rb +64 -0
  116. data/test/action_controller/explicit_serializer_test.rb +137 -0
  117. data/test/action_controller/json/include_test.rb +248 -0
  118. data/test/action_controller/json_api/deserialization_test.rb +114 -0
  119. data/test/action_controller/json_api/errors_test.rb +42 -0
  120. data/test/action_controller/json_api/fields_test.rb +68 -0
  121. data/test/action_controller/json_api/linked_test.rb +204 -0
  122. data/test/action_controller/json_api/pagination_test.rb +126 -0
  123. data/test/action_controller/json_api/transform_test.rb +191 -0
  124. data/test/action_controller/lookup_proc_test.rb +51 -0
  125. data/test/action_controller/namespace_lookup_test.rb +239 -0
  126. data/test/action_controller/serialization_scope_name_test.rb +237 -0
  127. data/test/action_controller/serialization_test.rb +480 -0
  128. data/test/active_model_serializers/adapter_for_test.rb +210 -0
  129. data/test/active_model_serializers/json_pointer_test.rb +24 -0
  130. data/test/active_model_serializers/logging_test.rb +79 -0
  131. data/test/active_model_serializers/model_test.rb +144 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
  133. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  134. data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
  135. data/test/active_model_serializers/test/schema_test.rb +133 -0
  136. data/test/active_model_serializers/test/serializer_test.rb +64 -0
  137. data/test/active_record_test.rb +11 -0
  138. data/test/adapter/attributes_test.rb +42 -0
  139. data/test/adapter/deprecation_test.rb +102 -0
  140. data/test/adapter/json/belongs_to_test.rb +47 -0
  141. data/test/adapter/json/collection_test.rb +106 -0
  142. data/test/adapter/json/has_many_test.rb +55 -0
  143. data/test/adapter/json/transform_test.rb +95 -0
  144. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  145. data/test/adapter/json_api/collection_test.rb +98 -0
  146. data/test/adapter/json_api/errors_test.rb +78 -0
  147. data/test/adapter/json_api/fields_test.rb +98 -0
  148. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  149. data/test/adapter/json_api/has_many_test.rb +175 -0
  150. data/test/adapter/json_api/has_one_test.rb +82 -0
  151. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  152. data/test/adapter/json_api/json_api_test.rb +35 -0
  153. data/test/adapter/json_api/linked_test.rb +415 -0
  154. data/test/adapter/json_api/links_test.rb +112 -0
  155. data/test/adapter/json_api/pagination_links_test.rb +208 -0
  156. data/test/adapter/json_api/parse_test.rb +139 -0
  157. data/test/adapter/json_api/relationship_test.rb +399 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +102 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  160. data/test/adapter/json_api/transform_test.rb +514 -0
  161. data/test/adapter/json_api/type_test.rb +195 -0
  162. data/test/adapter/json_test.rb +48 -0
  163. data/test/adapter/null_test.rb +24 -0
  164. data/test/adapter/polymorphic_test.rb +220 -0
  165. data/test/adapter_test.rb +69 -0
  166. data/test/array_serializer_test.rb +24 -0
  167. data/test/benchmark/app.rb +67 -0
  168. data/test/benchmark/benchmarking_support.rb +69 -0
  169. data/test/benchmark/bm_active_record.rb +83 -0
  170. data/test/benchmark/bm_adapter.rb +40 -0
  171. data/test/benchmark/bm_caching.rb +121 -0
  172. data/test/benchmark/bm_lookup_chain.rb +85 -0
  173. data/test/benchmark/bm_transform.rb +47 -0
  174. data/test/benchmark/config.ru +3 -0
  175. data/test/benchmark/controllers.rb +85 -0
  176. data/test/benchmark/fixtures.rb +221 -0
  177. data/test/cache_test.rb +717 -0
  178. data/test/collection_serializer_test.rb +129 -0
  179. data/test/fixtures/active_record.rb +115 -0
  180. data/test/fixtures/poro.rb +227 -0
  181. data/test/generators/scaffold_controller_generator_test.rb +26 -0
  182. data/test/generators/serializer_generator_test.rb +77 -0
  183. data/test/grape_test.rb +198 -0
  184. data/test/lint_test.rb +51 -0
  185. data/test/logger_test.rb +22 -0
  186. data/test/poro_test.rb +11 -0
  187. data/test/serializable_resource_test.rb +81 -0
  188. data/test/serializers/association_macros_test.rb +39 -0
  189. data/test/serializers/associations_test.rb +520 -0
  190. data/test/serializers/attribute_test.rb +155 -0
  191. data/test/serializers/attributes_test.rb +54 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +172 -0
  193. data/test/serializers/configuration_test.rb +34 -0
  194. data/test/serializers/fieldset_test.rb +16 -0
  195. data/test/serializers/meta_test.rb +204 -0
  196. data/test/serializers/options_test.rb +34 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
  198. data/test/serializers/reflection_test.rb +481 -0
  199. data/test/serializers/root_test.rb +23 -0
  200. data/test/serializers/serialization_test.rb +57 -0
  201. data/test/serializers/serializer_for_test.rb +138 -0
  202. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  203. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  204. data/test/support/isolated_unit.rb +86 -0
  205. data/test/support/rails5_shims.rb +55 -0
  206. data/test/support/rails_app.rb +40 -0
  207. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  208. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  209. data/test/support/schemas/custom/show.json +7 -0
  210. data/test/support/schemas/hyper_schema.json +93 -0
  211. data/test/support/schemas/render_using_json_api.json +43 -0
  212. data/test/support/schemas/simple_json_pointers.json +10 -0
  213. data/test/support/serialization_testing.rb +81 -0
  214. data/test/test_helper.rb +72 -0
  215. metadata +622 -0
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModelSerializers
6
+ class AdapterTest < ActiveSupport::TestCase
7
+ def setup
8
+ profile = Profile.new
9
+ @serializer = ProfileSerializer.new(profile)
10
+ @adapter = ActiveModelSerializers::Adapter::Base.new(@serializer)
11
+ end
12
+
13
+ def test_serializable_hash_is_abstract_method
14
+ assert_raises(NotImplementedError) do
15
+ @adapter.serializable_hash(only: [:name])
16
+ end
17
+ end
18
+
19
+ def test_serialization_options_ensures_option_is_a_hash
20
+ adapter = Class.new(ActiveModelSerializers::Adapter::Base) do
21
+ def serializable_hash(options = nil)
22
+ serialization_options(options)
23
+ end
24
+ end.new(@serializer)
25
+ assert_equal({}, adapter.serializable_hash(nil))
26
+ assert_equal({}, adapter.serializable_hash({}))
27
+ ensure
28
+ ActiveModelSerializers::Adapter.adapter_map.delete_if { |k, _| k =~ /class/ }
29
+ end
30
+
31
+ def test_serialization_options_ensures_option_is_one_of_valid_options
32
+ adapter = Class.new(ActiveModelSerializers::Adapter::Base) do
33
+ def serializable_hash(options = nil)
34
+ serialization_options(options)
35
+ end
36
+ end.new(@serializer)
37
+ filtered_options = { now: :see_me, then: :not }
38
+ valid_options = ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS.each_with_object({}) do |option, result|
39
+ result[option] = option
40
+ end
41
+ assert_equal(valid_options, adapter.serializable_hash(filtered_options.merge(valid_options)))
42
+ ensure
43
+ ActiveModelSerializers::Adapter.adapter_map.delete_if { |k, _| k =~ /class/ }
44
+ end
45
+
46
+ def test_serializer
47
+ assert_equal @serializer, @adapter.serializer
48
+ end
49
+
50
+ def test_create_adapter
51
+ adapter = ActiveModelSerializers::Adapter.create(@serializer)
52
+ assert_equal ActiveModelSerializers::Adapter::Attributes, adapter.class
53
+ end
54
+
55
+ def test_create_adapter_with_override
56
+ adapter = ActiveModelSerializers::Adapter.create(@serializer, adapter: :json_api)
57
+ assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
58
+ end
59
+
60
+ def test_inflected_adapter_class_for_known_adapter
61
+ ActiveSupport::Inflector.inflections(:en) { |inflect| inflect.acronym 'API' }
62
+ klass = ActiveModelSerializers::Adapter.adapter_class(:json_api)
63
+
64
+ ActiveSupport::Inflector.inflections.acronyms.clear
65
+
66
+ assert_equal ActiveModelSerializers::Adapter::JsonApi, klass
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require_relative 'collection_serializer_test'
5
+
6
+ module ActiveModel
7
+ class Serializer
8
+ class ArraySerializerTest < CollectionSerializerTest
9
+ extend Minitest::Assertions
10
+ def self.run_one_method(*)
11
+ _, stderr = capture_io do
12
+ super
13
+ end
14
+ if stderr !~ /NOTE: ActiveModel::Serializer::ArraySerializer.new is deprecated/
15
+ fail Minitest::Assertion, stderr
16
+ end
17
+ end
18
+
19
+ def collection_serializer
20
+ ArraySerializer
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ # https://github.com/rails-api/active_model_serializers/pull/872
4
+ # approx ref 792fb8a9053f8db3c562dae4f40907a582dd1720 to test against
5
+ require 'bundler/setup'
6
+
7
+ require 'rails'
8
+ require 'active_model'
9
+ require 'active_support'
10
+ require 'active_support/json'
11
+ require 'action_controller'
12
+ require 'action_controller/test_case'
13
+ require 'action_controller/railtie'
14
+ abort "Rails application already defined: #{Rails.application.class}" if Rails.application
15
+
16
+ class NullLogger < Logger
17
+ def initialize(*_args)
18
+ end
19
+
20
+ def add(*_args, &_block)
21
+ end
22
+ end
23
+ class BenchmarkLogger < ActiveSupport::Logger
24
+ def initialize
25
+ @file = StringIO.new
26
+ super(@file)
27
+ end
28
+
29
+ def messages
30
+ @file.rewind
31
+ @file.read
32
+ end
33
+ end
34
+ # ref: https://gist.github.com/bf4/8744473
35
+ class BenchmarkApp < Rails::Application
36
+ # Set up production configuration
37
+ config.eager_load = true
38
+ config.cache_classes = true
39
+ # CONFIG: CACHE_ON={on,off}
40
+ config.action_controller.perform_caching = ENV['CACHE_ON'] != 'off'
41
+ config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
42
+
43
+ config.active_support.test_order = :random
44
+ config.secret_token = 'S' * 30
45
+ config.secret_key_base = 'abc123'
46
+ config.consider_all_requests_local = false
47
+
48
+ # otherwise deadlock occurred
49
+ config.middleware.delete 'Rack::Lock'
50
+
51
+ # to disable log files
52
+ config.logger = NullLogger.new
53
+ config.active_support.deprecation = :log
54
+ config.log_level = :info
55
+ end
56
+
57
+ require 'active_model_serializers'
58
+
59
+ # Initialize app before any serializers are defined, for running across revisions.
60
+ # ref: https://github.com/rails-api/active_model_serializers/pull/1478
61
+ Rails.application.initialize!
62
+ # HACK: Serializer::cache depends on the ActionController-dependent configs being set.
63
+ ActiveSupport.on_load(:action_controller) do
64
+ require_relative 'fixtures'
65
+ end
66
+
67
+ require_relative 'controllers'
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/ips'
4
+ require 'json'
5
+
6
+ # Add benchmarking runner from ruby-bench-suite
7
+ # https://github.com/ruby-bench/ruby-bench-suite/blob/master/rails/benchmarks/support/benchmark_rails.rb
8
+ module Benchmark
9
+ module ActiveModelSerializers
10
+ module TestMethods
11
+ def request(method, path)
12
+ response = Rack::MockRequest.new(BenchmarkApp).send(method, path)
13
+ if response.status.in?([404, 500])
14
+ fail "omg, #{method}, #{path}, '#{response.status}', '#{response.body}'"
15
+ end
16
+ response
17
+ end
18
+ end
19
+
20
+ # extend Benchmark with an `ams` method
21
+ def ams(label = nil, time:, disable_gc: true, warmup: 3, &block)
22
+ fail ArgumentError.new, 'block should be passed' unless block_given?
23
+
24
+ if disable_gc
25
+ GC.disable
26
+ else
27
+ GC.enable
28
+ end
29
+
30
+ report = Benchmark.ips(time, warmup, true) do |x|
31
+ x.report(label) { yield }
32
+ end
33
+
34
+ entry = report.entries.first
35
+
36
+ output = {
37
+ label: label,
38
+ version: ::ActiveModel::Serializer::VERSION.to_s,
39
+ rails_version: ::Rails.version.to_s,
40
+ iterations_per_second: entry.ips,
41
+ iterations_per_second_standard_deviation: entry.error_percentage,
42
+ total_allocated_objects_per_iteration: count_total_allocated_objects(&block)
43
+ }.to_json
44
+
45
+ puts output
46
+ output
47
+ end
48
+
49
+ def count_total_allocated_objects
50
+ if block_given?
51
+ key =
52
+ if RUBY_VERSION < '2.2'
53
+ :total_allocated_object
54
+ else
55
+ :total_allocated_objects
56
+ end
57
+
58
+ before = GC.stat[key]
59
+ yield
60
+ after = GC.stat[key]
61
+ after - before
62
+ else
63
+ -1
64
+ end
65
+ end
66
+ end
67
+
68
+ extend Benchmark::ActiveModelSerializers
69
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './benchmarking_support'
4
+ require_relative './app'
5
+
6
+ time = 10
7
+ disable_gc = true
8
+
9
+ # This is to disable any key transform effects that may impact performance
10
+ ActiveModelSerializers.config.key_transform = :unaltered
11
+
12
+ ###########################################
13
+ # Setup active record models
14
+ ##########################################
15
+ require 'active_record'
16
+ require 'sqlite3'
17
+
18
+ # For debugging SQL output
19
+ # ActiveRecord::Base.logger = Logger.new(STDERR)
20
+
21
+ # Change the following to reflect your database settings
22
+ ActiveRecord::Base.establish_connection(
23
+ adapter: 'sqlite3',
24
+ database: ':memory:'
25
+ )
26
+
27
+ # Don't show migration output when constructing fake db
28
+ ActiveRecord::Migration.verbose = false
29
+
30
+ ActiveRecord::Schema.define do
31
+ create_table :authors, force: true do |t|
32
+ t.string :name
33
+ end
34
+
35
+ create_table :posts, force: true do |t|
36
+ t.text :body
37
+ t.string :title
38
+ t.references :author
39
+ end
40
+
41
+ create_table :profiles, force: true do |t|
42
+ t.text :project_url
43
+ t.text :bio
44
+ t.date :birthday
45
+ t.references :author
46
+ end
47
+ end
48
+
49
+ class Author < ActiveRecord::Base
50
+ has_one :profile
51
+ has_many :posts
52
+ end
53
+
54
+ class Post < ActiveRecord::Base
55
+ belongs_to :author
56
+ end
57
+
58
+ class Profile < ActiveRecord::Base
59
+ belongs_to :author
60
+ end
61
+
62
+ # Build out the data to serialize
63
+ author = Author.create(name: 'Preston Sego')
64
+ Profile.create(project_url: 'https://github.com/NullVoxPopuli', author: author)
65
+ 50.times do
66
+ Post.create(
67
+ body: 'something about how password restrictions are evil, and less secure, and with the math to prove it.',
68
+ title: 'Your bank is does not know how to do security',
69
+ author: author
70
+ )
71
+ end
72
+
73
+ Benchmark.ams('AR: attributes', time: time, disable_gc: disable_gc) do
74
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :attributes, include: 'profile,posts').serializable_hash
75
+ end
76
+
77
+ Benchmark.ams('AR: json', time: time, disable_gc: disable_gc) do
78
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :json, include: 'profile,posts').serializable_hash
79
+ end
80
+
81
+ Benchmark.ams('AR: JSON API', time: time, disable_gc: disable_gc) do
82
+ ActiveModelSerializers::SerializableResource.new(author, adapter: :json_api, include: 'profile,posts').serializable_hash
83
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './benchmarking_support'
4
+ require_relative './app'
5
+
6
+ time = 10
7
+ disable_gc = true
8
+ ActiveModelSerializers.config.key_transform = :unaltered
9
+ has_many_relationships = (0..60).map do |i|
10
+ HasManyRelationship.new(id: i, body: 'ZOMG A HAS MANY RELATIONSHIP')
11
+ end
12
+ has_one_relationship = HasOneRelationship.new(
13
+ id: 42,
14
+ first_name: 'Joao',
15
+ last_name: 'Moura'
16
+ )
17
+ primary_resource = PrimaryResource.new(
18
+ id: 1337,
19
+ title: 'New PrimaryResource',
20
+ virtual_attribute: nil,
21
+ body: 'Body',
22
+ has_many_relationships: has_many_relationships,
23
+ has_one_relationship: has_one_relationship
24
+ )
25
+ serializer = PrimaryResourceSerializer.new(primary_resource)
26
+
27
+ Benchmark.ams('attributes', time: time, disable_gc: disable_gc) do
28
+ attributes = ActiveModelSerializers::Adapter::Attributes.new(serializer)
29
+ attributes.as_json
30
+ end
31
+
32
+ Benchmark.ams('json_api', time: time, disable_gc: disable_gc) do
33
+ json_api = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
34
+ json_api.as_json
35
+ end
36
+
37
+ Benchmark.ams('json', time: time, disable_gc: disable_gc) do
38
+ json = ActiveModelSerializers::Adapter::Json.new(serializer)
39
+ json.as_json
40
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './benchmarking_support'
4
+ require_relative './app'
5
+
6
+ # https://github.com/ruby-bench/ruby-bench-suite/blob/8ad567f7e43a044ae48c36833218423bb1e2bd9d/rails/benchmarks/actionpack_router.rb
7
+ class ApiAssertion
8
+ include Benchmark::ActiveModelSerializers::TestMethods
9
+ class BadRevisionError < StandardError; end
10
+
11
+ def valid?
12
+ caching = get_caching
13
+ caching[:body].delete('meta')
14
+ non_caching = get_non_caching
15
+ non_caching[:body].delete('meta')
16
+ assert_responses(caching, non_caching)
17
+ rescue BadRevisionError => e
18
+ msg = { error: e.message }
19
+ STDERR.puts msg
20
+ STDOUT.puts msg
21
+ exit 1
22
+ end
23
+
24
+ def get_status(on_off = 'on'.freeze)
25
+ get("/status/#{on_off}")
26
+ end
27
+
28
+ def clear
29
+ get('/clear')
30
+ end
31
+
32
+ def get_caching(on_off = 'on'.freeze)
33
+ get("/caching/#{on_off}")
34
+ end
35
+
36
+ def get_fragment_caching(on_off = 'on'.freeze)
37
+ get("/fragment_caching/#{on_off}")
38
+ end
39
+
40
+ def get_non_caching(on_off = 'on'.freeze)
41
+ get("/non_caching/#{on_off}")
42
+ end
43
+
44
+ def debug(msg = '')
45
+ if block_given? && ENV['DEBUG'] =~ /\Atrue|on|0\z/i
46
+ STDERR.puts yield
47
+ else
48
+ STDERR.puts msg
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def assert_responses(caching, non_caching)
55
+ assert_equal(caching[:code], 200, "Caching response failed: #{caching}")
56
+ assert_equal(caching[:body], expected, "Caching response format failed: \n+ #{caching[:body]}\n- #{expected}")
57
+ assert_equal(caching[:content_type], 'application/json; charset=utf-8', "Caching response content type failed: \n+ #{caching[:content_type]}\n- application/json")
58
+ assert_equal(non_caching[:code], 200, "Non caching response failed: #{non_caching}")
59
+ assert_equal(non_caching[:body], expected, "Non Caching response format failed: \n+ #{non_caching[:body]}\n- #{expected}")
60
+ assert_equal(non_caching[:content_type], 'application/json; charset=utf-8', "Non caching response content type failed: \n+ #{non_caching[:content_type]}\n- application/json")
61
+ end
62
+
63
+ def get(url)
64
+ response = request(:get, url)
65
+ { code: response.status, body: JSON.load(response.body), content_type: response.content_type }
66
+ end
67
+
68
+ def expected
69
+ @expected ||=
70
+ {
71
+ 'primary_resource' => {
72
+ 'id' => 1337,
73
+ 'title' => 'New PrimaryResource',
74
+ 'body' => 'Body',
75
+ 'virtual_attribute' => {
76
+ 'id' => 999,
77
+ 'name' => 'Free-Range Virtual Attribute'
78
+ },
79
+ 'has_one_relationship' => {
80
+ 'id' => 42,
81
+ 'first_name' => 'Joao',
82
+ 'last_name' => 'Moura'
83
+ },
84
+ 'has_many_relationships' => [
85
+ {
86
+ 'id' => 1,
87
+ 'body' => 'ZOMG A HAS MANY RELATIONSHIP'
88
+ }
89
+ ]
90
+ }
91
+ }
92
+ end
93
+
94
+ def assert_equal(expected, actual, message)
95
+ return true if expected == actual
96
+ if ENV['FAIL_ASSERTION'] =~ /\Atrue|on|0\z/i # rubocop:disable Style/GuardClause
97
+ fail BadRevisionError, message
98
+ else
99
+ STDERR.puts message unless ENV['SUMMARIZE']
100
+ end
101
+ end
102
+ end
103
+ assertion = ApiAssertion.new
104
+ assertion.valid?
105
+ assertion.debug { assertion.get_status }
106
+
107
+ time = 10
108
+ {
109
+ 'caching on: caching serializers: gc off' => { disable_gc: true, send: [:get_caching, 'on'] },
110
+ 'caching on: fragment caching serializers: gc off' => { disable_gc: true, send: [:get_fragment_caching, 'on'] },
111
+ 'caching on: non-caching serializers: gc off' => { disable_gc: true, send: [:get_non_caching, 'on'] },
112
+ 'caching off: caching serializers: gc off' => { disable_gc: true, send: [:get_caching, 'off'] },
113
+ 'caching off: fragment caching serializers: gc off' => { disable_gc: true, send: [:get_fragment_caching, 'off'] },
114
+ 'caching off: non-caching serializers: gc off' => { disable_gc: true, send: [:get_non_caching, 'off'] }
115
+ }.each do |label, options|
116
+ assertion.clear
117
+ Benchmark.ams(label, time: time, disable_gc: options[:disable_gc]) do
118
+ assertion.send(*options[:send])
119
+ end
120
+ assertion.debug { assertion.get_status(options[:send][-1]) }
121
+ end