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.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +35 -0
- data/.rubocop.yml +109 -0
- data/.simplecov +110 -0
- data/.travis.yml +63 -0
- data/CHANGELOG.md +727 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +74 -0
- data/MIT-LICENSE +22 -0
- data/README.md +305 -0
- data/Rakefile +76 -0
- data/active_model_serializers.gemspec +64 -0
- data/appveyor.yml +28 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/rubocop +38 -0
- data/bin/serve_benchmark +39 -0
- data/docs/README.md +41 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +269 -0
- data/docs/general/caching.md +58 -0
- data/docs/general/configuration_options.md +185 -0
- data/docs/general/deserialization.md +100 -0
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +133 -0
- data/docs/general/instrumentation.md +40 -0
- data/docs/general/key_transforms.md +40 -0
- data/docs/general/logging.md +21 -0
- data/docs/general/rendering.md +293 -0
- data/docs/general/serializers.md +495 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +138 -0
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +62 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +66 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +73 -0
- data/docs/howto/test.md +154 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +147 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +76 -0
- data/lib/active_model/serializable_resource.rb +13 -0
- data/lib/active_model/serializer.rb +418 -0
- data/lib/active_model/serializer/adapter.rb +26 -0
- data/lib/active_model/serializer/adapter/attributes.rb +17 -0
- data/lib/active_model/serializer/adapter/base.rb +20 -0
- data/lib/active_model/serializer/adapter/json.rb +17 -0
- data/lib/active_model/serializer/adapter/json_api.rb +17 -0
- data/lib/active_model/serializer/adapter/null.rb +17 -0
- data/lib/active_model/serializer/array_serializer.rb +14 -0
- data/lib/active_model/serializer/association.rb +91 -0
- data/lib/active_model/serializer/attribute.rb +27 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
- data/lib/active_model/serializer/collection_serializer.rb +90 -0
- data/lib/active_model/serializer/concerns/caching.rb +304 -0
- data/lib/active_model/serializer/error_serializer.rb +16 -0
- data/lib/active_model/serializer/errors_serializer.rb +34 -0
- data/lib/active_model/serializer/field.rb +92 -0
- data/lib/active_model/serializer/fieldset.rb +33 -0
- data/lib/active_model/serializer/has_many_reflection.rb +12 -0
- data/lib/active_model/serializer/has_one_reflection.rb +9 -0
- data/lib/active_model/serializer/lazy_association.rb +99 -0
- data/lib/active_model/serializer/link.rb +23 -0
- data/lib/active_model/serializer/lint.rb +152 -0
- data/lib/active_model/serializer/null.rb +19 -0
- data/lib/active_model/serializer/reflection.rb +212 -0
- data/lib/active_model/serializer/version.rb +7 -0
- data/lib/active_model_serializers.rb +63 -0
- data/lib/active_model_serializers/adapter.rb +100 -0
- data/lib/active_model_serializers/adapter/attributes.rb +15 -0
- data/lib/active_model_serializers/adapter/base.rb +85 -0
- data/lib/active_model_serializers/adapter/json.rb +23 -0
- data/lib/active_model_serializers/adapter/json_api.rb +535 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
- data/lib/active_model_serializers/adapter/null.rb +11 -0
- data/lib/active_model_serializers/callbacks.rb +57 -0
- data/lib/active_model_serializers/deprecate.rb +56 -0
- data/lib/active_model_serializers/deserialization.rb +17 -0
- data/lib/active_model_serializers/json_pointer.rb +16 -0
- data/lib/active_model_serializers/logging.rb +124 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model.rb +132 -0
- data/lib/active_model_serializers/railtie.rb +52 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
- data/lib/active_model_serializers/serializable_resource.rb +84 -0
- data/lib/active_model_serializers/serialization_context.rb +41 -0
- data/lib/active_model_serializers/test.rb +9 -0
- data/lib/active_model_serializers/test/schema.rb +140 -0
- data/lib/active_model_serializers/test/serializer.rb +127 -0
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +12 -0
- data/lib/generators/rails/serializer_generator.rb +38 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +18 -0
- data/lib/grape/formatters/active_model_serializers.rb +34 -0
- data/lib/grape/helpers/active_model_serializers.rb +19 -0
- data/lib/tasks/rubocop.rake +55 -0
- data/test/action_controller/adapter_selector_test.rb +64 -0
- data/test/action_controller/explicit_serializer_test.rb +137 -0
- data/test/action_controller/json/include_test.rb +248 -0
- data/test/action_controller/json_api/deserialization_test.rb +114 -0
- data/test/action_controller/json_api/errors_test.rb +42 -0
- data/test/action_controller/json_api/fields_test.rb +68 -0
- data/test/action_controller/json_api/linked_test.rb +204 -0
- data/test/action_controller/json_api/pagination_test.rb +126 -0
- data/test/action_controller/json_api/transform_test.rb +191 -0
- data/test/action_controller/lookup_proc_test.rb +51 -0
- data/test/action_controller/namespace_lookup_test.rb +239 -0
- data/test/action_controller/serialization_scope_name_test.rb +237 -0
- data/test/action_controller/serialization_test.rb +480 -0
- data/test/active_model_serializers/adapter_for_test.rb +210 -0
- data/test/active_model_serializers/json_pointer_test.rb +24 -0
- data/test/active_model_serializers/logging_test.rb +79 -0
- data/test/active_model_serializers/model_test.rb +144 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
- data/test/active_model_serializers/test/schema_test.rb +133 -0
- data/test/active_model_serializers/test/serializer_test.rb +64 -0
- data/test/active_record_test.rb +11 -0
- data/test/adapter/attributes_test.rb +42 -0
- data/test/adapter/deprecation_test.rb +102 -0
- data/test/adapter/json/belongs_to_test.rb +47 -0
- data/test/adapter/json/collection_test.rb +106 -0
- data/test/adapter/json/has_many_test.rb +55 -0
- data/test/adapter/json/transform_test.rb +95 -0
- data/test/adapter/json_api/belongs_to_test.rb +157 -0
- data/test/adapter/json_api/collection_test.rb +98 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +98 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
- data/test/adapter/json_api/has_many_test.rb +175 -0
- data/test/adapter/json_api/has_one_test.rb +82 -0
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +415 -0
- data/test/adapter/json_api/links_test.rb +112 -0
- data/test/adapter/json_api/pagination_links_test.rb +208 -0
- data/test/adapter/json_api/parse_test.rb +139 -0
- data/test/adapter/json_api/relationship_test.rb +399 -0
- data/test/adapter/json_api/resource_meta_test.rb +102 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
- data/test/adapter/json_api/transform_test.rb +514 -0
- data/test/adapter/json_api/type_test.rb +195 -0
- data/test/adapter/json_test.rb +48 -0
- data/test/adapter/null_test.rb +24 -0
- data/test/adapter/polymorphic_test.rb +220 -0
- data/test/adapter_test.rb +69 -0
- data/test/array_serializer_test.rb +24 -0
- data/test/benchmark/app.rb +67 -0
- data/test/benchmark/benchmarking_support.rb +69 -0
- data/test/benchmark/bm_active_record.rb +83 -0
- data/test/benchmark/bm_adapter.rb +40 -0
- data/test/benchmark/bm_caching.rb +121 -0
- data/test/benchmark/bm_lookup_chain.rb +85 -0
- data/test/benchmark/bm_transform.rb +47 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +85 -0
- data/test/benchmark/fixtures.rb +221 -0
- data/test/cache_test.rb +717 -0
- data/test/collection_serializer_test.rb +129 -0
- data/test/fixtures/active_record.rb +115 -0
- data/test/fixtures/poro.rb +227 -0
- data/test/generators/scaffold_controller_generator_test.rb +26 -0
- data/test/generators/serializer_generator_test.rb +77 -0
- data/test/grape_test.rb +198 -0
- data/test/lint_test.rb +51 -0
- data/test/logger_test.rb +22 -0
- data/test/poro_test.rb +11 -0
- data/test/serializable_resource_test.rb +81 -0
- data/test/serializers/association_macros_test.rb +39 -0
- data/test/serializers/associations_test.rb +520 -0
- data/test/serializers/attribute_test.rb +155 -0
- data/test/serializers/attributes_test.rb +54 -0
- data/test/serializers/caching_configuration_test_isolated.rb +172 -0
- data/test/serializers/configuration_test.rb +34 -0
- data/test/serializers/fieldset_test.rb +16 -0
- data/test/serializers/meta_test.rb +204 -0
- data/test/serializers/options_test.rb +34 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
- data/test/serializers/reflection_test.rb +481 -0
- data/test/serializers/root_test.rb +23 -0
- data/test/serializers/serialization_test.rb +57 -0
- data/test/serializers/serializer_for_test.rb +138 -0
- data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +86 -0
- data/test/support/rails5_shims.rb +55 -0
- data/test/support/rails_app.rb +40 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
- data/test/support/schemas/custom/show.json +7 -0
- data/test/support/schemas/hyper_schema.json +93 -0
- data/test/support/schemas/render_using_json_api.json +43 -0
- data/test/support/schemas/simple_json_pointers.json +10 -0
- data/test/support/serialization_testing.rb +81 -0
- data/test/test_helper.rb +72 -0
- 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
|