active_model_serializers 0.10.0 → 0.10.13
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 +5 -5
- data/CHANGELOG.md +239 -2
- data/README.md +171 -34
- data/lib/action_controller/serialization.rb +23 -3
- data/lib/active_model/serializable_resource.rb +2 -0
- data/lib/active_model/serializer/adapter/attributes.rb +2 -0
- data/lib/active_model/serializer/adapter/base.rb +4 -0
- data/lib/active_model/serializer/adapter/json.rb +2 -0
- data/lib/active_model/serializer/adapter/json_api.rb +2 -0
- data/lib/active_model/serializer/adapter/null.rb +2 -0
- data/lib/active_model/serializer/adapter.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +10 -5
- data/lib/active_model/serializer/association.rb +64 -10
- data/lib/active_model/serializer/attribute.rb +2 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
- data/lib/active_model/serializer/collection_serializer.rb +48 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +89 -117
- data/lib/active_model/serializer/error_serializer.rb +13 -7
- data/lib/active_model/serializer/errors_serializer.rb +27 -20
- data/lib/active_model/serializer/field.rb +2 -0
- data/lib/active_model/serializer/fieldset.rb +3 -1
- data/lib/active_model/serializer/has_many_reflection.rb +5 -3
- data/lib/active_model/serializer/has_one_reflection.rb +3 -4
- 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 +136 -130
- data/lib/active_model/serializer/null.rb +2 -0
- data/lib/active_model/serializer/reflection.rb +130 -65
- data/lib/active_model/serializer/version.rb +3 -1
- data/lib/active_model/serializer.rb +321 -86
- data/lib/active_model_serializers/adapter/attributes.rb +17 -57
- data/lib/active_model_serializers/adapter/base.rb +41 -39
- data/lib/active_model_serializers/adapter/json.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
- data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
- data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +52 -20
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
- data/lib/active_model_serializers/adapter/json_api.rb +84 -65
- data/lib/active_model_serializers/adapter/null.rb +2 -0
- data/lib/active_model_serializers/adapter.rb +9 -1
- data/lib/active_model_serializers/callbacks.rb +2 -0
- data/lib/active_model_serializers/deprecate.rb +3 -2
- data/lib/active_model_serializers/deserialization.rb +4 -0
- data/lib/active_model_serializers/json_pointer.rb +2 -0
- data/lib/active_model_serializers/logging.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +82 -0
- data/lib/active_model_serializers/model/caching.rb +26 -0
- data/lib/active_model_serializers/model.rb +111 -28
- data/lib/active_model_serializers/railtie.rb +7 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
- data/lib/active_model_serializers/serializable_resource.rb +10 -7
- data/lib/active_model_serializers/serialization_context.rb +12 -3
- data/lib/active_model_serializers/test/schema.rb +4 -2
- data/lib/active_model_serializers/test/serializer.rb +2 -0
- data/lib/active_model_serializers/test.rb +2 -0
- data/lib/active_model_serializers.rb +35 -10
- data/lib/generators/rails/resource_override.rb +3 -1
- data/lib/generators/rails/serializer_generator.rb +6 -4
- data/lib/grape/active_model_serializers.rb +9 -5
- data/lib/grape/formatters/active_model_serializers.rb +21 -2
- data/lib/grape/helpers/active_model_serializers.rb +3 -0
- data/lib/tasks/rubocop.rake +55 -0
- metadata +104 -296
- data/.github/ISSUE_TEMPLATE.md +0 -29
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -15
- data/.gitignore +0 -35
- data/.rubocop.yml +0 -104
- data/.rubocop_todo.yml +0 -167
- data/.simplecov +0 -110
- data/.travis.yml +0 -43
- data/CONTRIBUTING.md +0 -105
- data/Gemfile +0 -53
- data/Rakefile +0 -103
- data/active_model_serializers.gemspec +0 -66
- data/appveyor.yml +0 -24
- data/bin/bench +0 -171
- data/bin/bench_regression +0 -316
- data/bin/serve_benchmark +0 -39
- data/docs/ARCHITECTURE.md +0 -126
- data/docs/README.md +0 -40
- data/docs/STYLE.md +0 -58
- data/docs/general/adapters.md +0 -245
- data/docs/general/caching.md +0 -52
- data/docs/general/configuration_options.md +0 -100
- data/docs/general/deserialization.md +0 -100
- data/docs/general/getting_started.md +0 -133
- data/docs/general/instrumentation.md +0 -40
- data/docs/general/key_transforms.md +0 -40
- data/docs/general/logging.md +0 -14
- data/docs/general/rendering.md +0 -255
- data/docs/general/serializers.md +0 -372
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +0 -139
- data/docs/howto/add_root_key.md +0 -51
- data/docs/howto/outside_controller_use.md +0 -58
- data/docs/howto/passing_arbitrary_options.md +0 -27
- data/docs/howto/serialize_poro.md +0 -32
- data/docs/howto/test.md +0 -152
- data/docs/integrations/ember-and-json-api.md +0 -112
- data/docs/integrations/grape.md +0 -19
- data/docs/jsonapi/errors.md +0 -56
- data/docs/jsonapi/schema/schema.json +0 -366
- data/docs/jsonapi/schema.md +0 -151
- data/docs/rfcs/0000-namespace.md +0 -106
- data/docs/rfcs/template.md +0 -15
- data/lib/active_model/serializer/associations.rb +0 -100
- data/lib/active_model/serializer/attributes.rb +0 -82
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/configuration.rb +0 -35
- data/lib/active_model/serializer/include_tree.rb +0 -111
- data/lib/active_model/serializer/links.rb +0 -35
- data/lib/active_model/serializer/meta.rb +0 -29
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
- data/lib/active_model/serializer/type.rb +0 -25
- data/lib/active_model_serializers/key_transform.rb +0 -70
- data/test/action_controller/adapter_selector_test.rb +0 -53
- data/test/action_controller/explicit_serializer_test.rb +0 -134
- data/test/action_controller/json/include_test.rb +0 -167
- data/test/action_controller/json_api/deserialization_test.rb +0 -112
- data/test/action_controller/json_api/errors_test.rb +0 -41
- data/test/action_controller/json_api/linked_test.rb +0 -197
- data/test/action_controller/json_api/pagination_test.rb +0 -116
- data/test/action_controller/json_api/transform_test.rb +0 -181
- data/test/action_controller/serialization_scope_name_test.rb +0 -229
- data/test/action_controller/serialization_test.rb +0 -469
- data/test/active_model_serializers/adapter_for_test.rb +0 -208
- data/test/active_model_serializers/json_pointer_test.rb +0 -20
- data/test/active_model_serializers/key_transform_test.rb +0 -263
- data/test/active_model_serializers/logging_test.rb +0 -77
- data/test/active_model_serializers/model_test.rb +0 -9
- data/test/active_model_serializers/railtie_test_isolated.rb +0 -63
- data/test/active_model_serializers/serialization_context_test_isolated.rb +0 -58
- data/test/active_model_serializers/test/schema_test.rb +0 -130
- data/test/active_model_serializers/test/serializer_test.rb +0 -62
- data/test/active_record_test.rb +0 -9
- data/test/adapter/deprecation_test.rb +0 -100
- data/test/adapter/json/belongs_to_test.rb +0 -45
- data/test/adapter/json/collection_test.rb +0 -90
- data/test/adapter/json/has_many_test.rb +0 -45
- data/test/adapter/json/transform_test.rb +0 -93
- data/test/adapter/json_api/belongs_to_test.rb +0 -155
- data/test/adapter/json_api/collection_test.rb +0 -95
- data/test/adapter/json_api/errors_test.rb +0 -78
- data/test/adapter/json_api/fields_test.rb +0 -87
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +0 -96
- data/test/adapter/json_api/has_many_test.rb +0 -144
- data/test/adapter/json_api/has_one_test.rb +0 -80
- data/test/adapter/json_api/json_api_test.rb +0 -35
- data/test/adapter/json_api/linked_test.rb +0 -392
- data/test/adapter/json_api/links_test.rb +0 -93
- data/test/adapter/json_api/pagination_links_test.rb +0 -166
- data/test/adapter/json_api/parse_test.rb +0 -137
- data/test/adapter/json_api/relationship_test.rb +0 -161
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- data/test/adapter/json_api/resource_meta_test.rb +0 -100
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +0 -82
- data/test/adapter/json_api/transform_test.rb +0 -502
- data/test/adapter/json_api/type_test.rb +0 -61
- data/test/adapter/json_test.rb +0 -45
- data/test/adapter/null_test.rb +0 -23
- data/test/adapter/polymorphic_test.rb +0 -171
- data/test/adapter_test.rb +0 -67
- data/test/array_serializer_test.rb +0 -22
- data/test/benchmark/app.rb +0 -65
- data/test/benchmark/benchmarking_support.rb +0 -67
- data/test/benchmark/bm_caching.rb +0 -119
- data/test/benchmark/bm_transform.rb +0 -34
- data/test/benchmark/config.ru +0 -3
- data/test/benchmark/controllers.rb +0 -84
- data/test/benchmark/fixtures.rb +0 -219
- data/test/cache_test.rb +0 -485
- data/test/collection_serializer_test.rb +0 -110
- data/test/fixtures/active_record.rb +0 -78
- data/test/fixtures/poro.rb +0 -282
- data/test/generators/scaffold_controller_generator_test.rb +0 -24
- data/test/generators/serializer_generator_test.rb +0 -57
- data/test/grape_test.rb +0 -82
- data/test/include_tree/from_include_args_test.rb +0 -26
- data/test/include_tree/from_string_test.rb +0 -94
- data/test/include_tree/include_args_to_hash_test.rb +0 -64
- data/test/lint_test.rb +0 -49
- data/test/logger_test.rb +0 -18
- data/test/poro_test.rb +0 -9
- data/test/serializable_resource_test.rb +0 -83
- data/test/serializers/association_macros_test.rb +0 -36
- data/test/serializers/associations_test.rb +0 -295
- data/test/serializers/attribute_test.rb +0 -151
- data/test/serializers/attributes_test.rb +0 -52
- data/test/serializers/caching_configuration_test_isolated.rb +0 -170
- data/test/serializers/configuration_test.rb +0 -32
- data/test/serializers/fieldset_test.rb +0 -14
- data/test/serializers/meta_test.rb +0 -196
- data/test/serializers/options_test.rb +0 -21
- data/test/serializers/read_attribute_for_serialization_test.rb +0 -79
- data/test/serializers/root_test.rb +0 -21
- data/test/serializers/serialization_test.rb +0 -55
- data/test/serializers/serializer_for_test.rb +0 -134
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/isolated_unit.rb +0 -79
- data/test/support/rails5_shims.rb +0 -47
- data/test/support/rails_app.rb +0 -45
- data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +0 -6
- data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +0 -6
- data/test/support/schemas/custom/show.json +0 -7
- data/test/support/schemas/hyper_schema.json +0 -93
- data/test/support/schemas/render_using_json_api.json +0 -43
- data/test/support/schemas/simple_json_pointers.json +0 -10
- data/test/support/serialization_testing.rb +0 -53
- data/test/test_helper.rb +0 -57
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
|
|
3
|
-
module ActiveModel
|
|
4
|
-
class Serializer
|
|
5
|
-
module Adapter
|
|
6
|
-
class PolymorphicTest < ActiveSupport::TestCase
|
|
7
|
-
setup do
|
|
8
|
-
@employee = Employee.new(id: 42, name: 'Zoop Zoopler', email: 'zoop@example.com')
|
|
9
|
-
@picture = @employee.pictures.new(id: 1, title: 'headshot-1.jpg')
|
|
10
|
-
@picture.imageable = @employee
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def serialization(resource, adapter = :attributes)
|
|
14
|
-
serializable(resource, adapter: adapter, serializer: PolymorphicBelongsToSerializer).as_json
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def tag_serialization(adapter = :attributes)
|
|
18
|
-
tag = PolyTag.new(id: 1, phrase: 'foo')
|
|
19
|
-
tag.object_tags << ObjectTag.new(id: 1, poly_tag_id: 1, taggable: @employee)
|
|
20
|
-
tag.object_tags << ObjectTag.new(id: 5, poly_tag_id: 1, taggable: @picture)
|
|
21
|
-
serializable(tag, adapter: adapter, serializer: PolymorphicTagSerializer, include: '*.*').as_json
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def test_attributes_serialization
|
|
25
|
-
expected =
|
|
26
|
-
{
|
|
27
|
-
id: 1,
|
|
28
|
-
title: 'headshot-1.jpg',
|
|
29
|
-
imageable: {
|
|
30
|
-
type: 'employee',
|
|
31
|
-
employee: {
|
|
32
|
-
id: 42,
|
|
33
|
-
name: 'Zoop Zoopler'
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
assert_equal(expected, serialization(@picture))
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def test_attributes_serialization_without_polymorphic_association
|
|
42
|
-
expected =
|
|
43
|
-
{
|
|
44
|
-
id: 2,
|
|
45
|
-
title: 'headshot-2.jpg',
|
|
46
|
-
imageable: nil
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
simple_picture = Picture.new(id: 2, title: 'headshot-2.jpg')
|
|
50
|
-
assert_equal(expected, serialization(simple_picture))
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def test_attributes_serialization_with_polymorphic_has_many
|
|
54
|
-
expected =
|
|
55
|
-
{
|
|
56
|
-
id: 1,
|
|
57
|
-
phrase: 'foo',
|
|
58
|
-
object_tags: [
|
|
59
|
-
{
|
|
60
|
-
id: 1,
|
|
61
|
-
taggable: {
|
|
62
|
-
type: 'employee',
|
|
63
|
-
employee: {
|
|
64
|
-
id: 42
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
id: 5,
|
|
70
|
-
taggable: {
|
|
71
|
-
type: 'picture',
|
|
72
|
-
picture: {
|
|
73
|
-
id: 1
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
]
|
|
78
|
-
}
|
|
79
|
-
assert_equal(expected, tag_serialization)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def test_json_serialization
|
|
83
|
-
expected =
|
|
84
|
-
{
|
|
85
|
-
picture: {
|
|
86
|
-
id: 1,
|
|
87
|
-
title: 'headshot-1.jpg',
|
|
88
|
-
imageable: {
|
|
89
|
-
type: 'employee',
|
|
90
|
-
employee: {
|
|
91
|
-
id: 42,
|
|
92
|
-
name: 'Zoop Zoopler'
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
assert_equal(expected, serialization(@picture, :json))
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def test_json_serialization_without_polymorphic_association
|
|
102
|
-
expected =
|
|
103
|
-
{
|
|
104
|
-
picture: {
|
|
105
|
-
id: 2,
|
|
106
|
-
title: 'headshot-2.jpg',
|
|
107
|
-
imageable: nil
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
simple_picture = Picture.new(id: 2, title: 'headshot-2.jpg')
|
|
112
|
-
assert_equal(expected, serialization(simple_picture, :json))
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
def test_json_serialization_with_polymorphic_has_many
|
|
116
|
-
expected =
|
|
117
|
-
{
|
|
118
|
-
poly_tag: {
|
|
119
|
-
id: 1,
|
|
120
|
-
phrase: 'foo',
|
|
121
|
-
object_tags: [
|
|
122
|
-
{
|
|
123
|
-
id: 1,
|
|
124
|
-
taggable: {
|
|
125
|
-
type: 'employee',
|
|
126
|
-
employee: {
|
|
127
|
-
id: 42
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
id: 5,
|
|
133
|
-
taggable: {
|
|
134
|
-
type: 'picture',
|
|
135
|
-
picture: {
|
|
136
|
-
id: 1
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
]
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
assert_equal(expected, tag_serialization(:json))
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def test_json_api_serialization
|
|
147
|
-
expected =
|
|
148
|
-
{
|
|
149
|
-
data: {
|
|
150
|
-
id: '1',
|
|
151
|
-
type: 'pictures',
|
|
152
|
-
attributes: {
|
|
153
|
-
title: 'headshot-1.jpg'
|
|
154
|
-
},
|
|
155
|
-
relationships: {
|
|
156
|
-
imageable: {
|
|
157
|
-
data: {
|
|
158
|
-
id: '42',
|
|
159
|
-
type: 'employees'
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
assert_equal(expected, serialization(@picture, :json_api))
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
end
|
|
171
|
-
end
|
data/test/adapter_test.rb
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
|
|
3
|
-
module ActiveModelSerializers
|
|
4
|
-
class AdapterTest < ActiveSupport::TestCase
|
|
5
|
-
def setup
|
|
6
|
-
profile = Profile.new
|
|
7
|
-
@serializer = ProfileSerializer.new(profile)
|
|
8
|
-
@adapter = ActiveModelSerializers::Adapter::Base.new(@serializer)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def test_serializable_hash_is_abstract_method
|
|
12
|
-
assert_raises(NotImplementedError) do
|
|
13
|
-
@adapter.serializable_hash(only: [:name])
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def test_serialization_options_ensures_option_is_a_hash
|
|
18
|
-
adapter = Class.new(ActiveModelSerializers::Adapter::Base) do
|
|
19
|
-
def serializable_hash(options = nil)
|
|
20
|
-
serialization_options(options)
|
|
21
|
-
end
|
|
22
|
-
end.new(@serializer)
|
|
23
|
-
assert_equal({}, adapter.serializable_hash(nil))
|
|
24
|
-
assert_equal({}, adapter.serializable_hash({}))
|
|
25
|
-
ensure
|
|
26
|
-
ActiveModelSerializers::Adapter.adapter_map.delete_if { |k, _| k =~ /class/ }
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def test_serialization_options_ensures_option_is_one_of_valid_options
|
|
30
|
-
adapter = Class.new(ActiveModelSerializers::Adapter::Base) do
|
|
31
|
-
def serializable_hash(options = nil)
|
|
32
|
-
serialization_options(options)
|
|
33
|
-
end
|
|
34
|
-
end.new(@serializer)
|
|
35
|
-
filtered_options = { now: :see_me, then: :not }
|
|
36
|
-
valid_options = ActiveModel::Serializer::SERIALIZABLE_HASH_VALID_KEYS.each_with_object({}) do |option, result|
|
|
37
|
-
result[option] = option
|
|
38
|
-
end
|
|
39
|
-
assert_equal(valid_options, adapter.serializable_hash(filtered_options.merge(valid_options)))
|
|
40
|
-
ensure
|
|
41
|
-
ActiveModelSerializers::Adapter.adapter_map.delete_if { |k, _| k =~ /class/ }
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def test_serializer
|
|
45
|
-
assert_equal @serializer, @adapter.serializer
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def test_create_adapter
|
|
49
|
-
adapter = ActiveModelSerializers::Adapter.create(@serializer)
|
|
50
|
-
assert_equal ActiveModelSerializers::Adapter::Attributes, adapter.class
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def test_create_adapter_with_override
|
|
54
|
-
adapter = ActiveModelSerializers::Adapter.create(@serializer, { adapter: :json_api })
|
|
55
|
-
assert_equal ActiveModelSerializers::Adapter::JsonApi, adapter.class
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def test_inflected_adapter_class_for_known_adapter
|
|
59
|
-
ActiveSupport::Inflector.inflections(:en) { |inflect| inflect.acronym 'API' }
|
|
60
|
-
klass = ActiveModelSerializers::Adapter.adapter_class(:json_api)
|
|
61
|
-
|
|
62
|
-
ActiveSupport::Inflector.inflections.acronyms.clear
|
|
63
|
-
|
|
64
|
-
assert_equal ActiveModelSerializers::Adapter::JsonApi, klass
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require_relative 'collection_serializer_test'
|
|
3
|
-
|
|
4
|
-
module ActiveModel
|
|
5
|
-
class Serializer
|
|
6
|
-
class ArraySerializerTest < CollectionSerializerTest
|
|
7
|
-
extend Minitest::Assertions
|
|
8
|
-
def self.run_one_method(*)
|
|
9
|
-
_, stderr = capture_io do
|
|
10
|
-
super
|
|
11
|
-
end
|
|
12
|
-
if stderr !~ /NOTE: ActiveModel::Serializer::ArraySerializer.new is deprecated/
|
|
13
|
-
fail Minitest::Assertion, stderr
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def collection_serializer
|
|
18
|
-
ArraySerializer
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/test/benchmark/app.rb
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# https://github.com/rails-api/active_model_serializers/pull/872
|
|
2
|
-
# approx ref 792fb8a9053f8db3c562dae4f40907a582dd1720 to test against
|
|
3
|
-
require 'bundler/setup'
|
|
4
|
-
|
|
5
|
-
require 'rails'
|
|
6
|
-
require 'active_model'
|
|
7
|
-
require 'active_support'
|
|
8
|
-
require 'active_support/json'
|
|
9
|
-
require 'action_controller'
|
|
10
|
-
require 'action_controller/test_case'
|
|
11
|
-
require 'action_controller/railtie'
|
|
12
|
-
abort "Rails application already defined: #{Rails.application.class}" if Rails.application
|
|
13
|
-
|
|
14
|
-
class NullLogger < Logger
|
|
15
|
-
def initialize(*_args)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def add(*_args, &_block)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
class BenchmarkLogger < ActiveSupport::Logger
|
|
22
|
-
def initialize
|
|
23
|
-
@file = StringIO.new
|
|
24
|
-
super(@file)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def messages
|
|
28
|
-
@file.rewind
|
|
29
|
-
@file.read
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
# ref: https://gist.github.com/bf4/8744473
|
|
33
|
-
class BenchmarkApp < Rails::Application
|
|
34
|
-
# Set up production configuration
|
|
35
|
-
config.eager_load = true
|
|
36
|
-
config.cache_classes = true
|
|
37
|
-
# CONFIG: CACHE_ON={on,off}
|
|
38
|
-
config.action_controller.perform_caching = ENV['CACHE_ON'] != 'off'
|
|
39
|
-
config.action_controller.cache_store = ActiveSupport::Cache.lookup_store(:memory_store)
|
|
40
|
-
|
|
41
|
-
config.active_support.test_order = :random
|
|
42
|
-
config.secret_token = 'S' * 30
|
|
43
|
-
config.secret_key_base = 'abc123'
|
|
44
|
-
config.consider_all_requests_local = false
|
|
45
|
-
|
|
46
|
-
# otherwise deadlock occured
|
|
47
|
-
config.middleware.delete 'Rack::Lock'
|
|
48
|
-
|
|
49
|
-
# to disable log files
|
|
50
|
-
config.logger = NullLogger.new
|
|
51
|
-
config.active_support.deprecation = :log
|
|
52
|
-
config.log_level = :info
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
require 'active_model_serializers'
|
|
56
|
-
|
|
57
|
-
# Initialize app before any serializers are defined, for running across revisions.
|
|
58
|
-
# ref: https://github.com/rails-api/active_model_serializers/pull/1478
|
|
59
|
-
Rails.application.initialize!
|
|
60
|
-
# HACK: Serializer::cache depends on the ActionController-dependent configs being set.
|
|
61
|
-
ActiveSupport.on_load(:action_controller) do
|
|
62
|
-
require_relative 'fixtures'
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
require_relative 'controllers'
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
require 'benchmark/ips'
|
|
2
|
-
require 'json'
|
|
3
|
-
|
|
4
|
-
# Add benchmarking runner from ruby-bench-suite
|
|
5
|
-
# https://github.com/ruby-bench/ruby-bench-suite/blob/master/rails/benchmarks/support/benchmark_rails.rb
|
|
6
|
-
module Benchmark
|
|
7
|
-
module ActiveModelSerializers
|
|
8
|
-
module TestMethods
|
|
9
|
-
def request(method, path)
|
|
10
|
-
response = Rack::MockRequest.new(BenchmarkApp).send(method, path)
|
|
11
|
-
if response.status.in?([404, 500])
|
|
12
|
-
fail "omg, #{method}, #{path}, '#{response.status}', '#{response.body}'"
|
|
13
|
-
end
|
|
14
|
-
response
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# extend Benchmark with an `ams` method
|
|
19
|
-
def ams(label = nil, time:, disable_gc: true, warmup: 3, &block)
|
|
20
|
-
fail ArgumentError.new, 'block should be passed' unless block_given?
|
|
21
|
-
|
|
22
|
-
if disable_gc
|
|
23
|
-
GC.disable
|
|
24
|
-
else
|
|
25
|
-
GC.enable
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
report = Benchmark.ips(time, warmup, true) do |x|
|
|
29
|
-
x.report(label) { yield }
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
entry = report.entries.first
|
|
33
|
-
|
|
34
|
-
output = {
|
|
35
|
-
label: label,
|
|
36
|
-
version: ::ActiveModel::Serializer::VERSION.to_s,
|
|
37
|
-
rails_version: ::Rails.version.to_s,
|
|
38
|
-
iterations_per_second: entry.ips,
|
|
39
|
-
iterations_per_second_standard_deviation: entry.stddev_percentage,
|
|
40
|
-
total_allocated_objects_per_iteration: count_total_allocated_objects(&block)
|
|
41
|
-
}.to_json
|
|
42
|
-
|
|
43
|
-
puts output
|
|
44
|
-
output
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def count_total_allocated_objects
|
|
48
|
-
if block_given?
|
|
49
|
-
key =
|
|
50
|
-
if RUBY_VERSION < '2.2'
|
|
51
|
-
:total_allocated_object
|
|
52
|
-
else
|
|
53
|
-
:total_allocated_objects
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
before = GC.stat[key]
|
|
57
|
-
yield
|
|
58
|
-
after = GC.stat[key]
|
|
59
|
-
after - before
|
|
60
|
-
else
|
|
61
|
-
-1
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
extend Benchmark::ActiveModelSerializers
|
|
67
|
-
end
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
require_relative './benchmarking_support'
|
|
2
|
-
require_relative './app'
|
|
3
|
-
|
|
4
|
-
# https://github.com/ruby-bench/ruby-bench-suite/blob/8ad567f7e43a044ae48c36833218423bb1e2bd9d/rails/benchmarks/actionpack_router.rb
|
|
5
|
-
class ApiAssertion
|
|
6
|
-
include Benchmark::ActiveModelSerializers::TestMethods
|
|
7
|
-
BadRevisionError = Class.new(StandardError)
|
|
8
|
-
|
|
9
|
-
def valid?
|
|
10
|
-
caching = get_caching
|
|
11
|
-
caching[:body].delete('meta')
|
|
12
|
-
non_caching = get_non_caching
|
|
13
|
-
non_caching[:body].delete('meta')
|
|
14
|
-
assert_responses(caching, non_caching)
|
|
15
|
-
rescue BadRevisionError => e
|
|
16
|
-
msg = { error: e.message }
|
|
17
|
-
STDERR.puts msg
|
|
18
|
-
STDOUT.puts msg
|
|
19
|
-
exit 1
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def get_status(on_off = 'on'.freeze)
|
|
23
|
-
get("/status/#{on_off}")
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def clear
|
|
27
|
-
get('/clear')
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def get_caching(on_off = 'on'.freeze)
|
|
31
|
-
get("/caching/#{on_off}")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def get_fragment_caching(on_off = 'on'.freeze)
|
|
35
|
-
get("/fragment_caching/#{on_off}")
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def get_non_caching(on_off = 'on'.freeze)
|
|
39
|
-
get("/non_caching/#{on_off}")
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def debug(msg = '')
|
|
43
|
-
if block_given? && ENV['DEBUG'] =~ /\Atrue|on|0\z/i
|
|
44
|
-
STDERR.puts yield
|
|
45
|
-
else
|
|
46
|
-
STDERR.puts msg
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
private
|
|
51
|
-
|
|
52
|
-
def assert_responses(caching, non_caching)
|
|
53
|
-
assert_equal(caching[:code], 200, "Caching response failed: #{caching}")
|
|
54
|
-
assert_equal(caching[:body], expected, "Caching response format failed: \n+ #{caching[:body]}\n- #{expected}")
|
|
55
|
-
assert_equal(caching[:content_type], 'application/json; charset=utf-8', "Caching response content type failed: \n+ #{caching[:content_type]}\n- application/json")
|
|
56
|
-
assert_equal(non_caching[:code], 200, "Non caching response failed: #{non_caching}")
|
|
57
|
-
assert_equal(non_caching[:body], expected, "Non Caching response format failed: \n+ #{non_caching[:body]}\n- #{expected}")
|
|
58
|
-
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")
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def get(url)
|
|
62
|
-
response = request(:get, url)
|
|
63
|
-
{ code: response.status, body: JSON.load(response.body), content_type: response.content_type }
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def expected
|
|
67
|
-
@expected ||=
|
|
68
|
-
{
|
|
69
|
-
'post' => {
|
|
70
|
-
'id' => 1337,
|
|
71
|
-
'title' => 'New Post',
|
|
72
|
-
'body' => 'Body',
|
|
73
|
-
'comments' => [
|
|
74
|
-
{
|
|
75
|
-
'id' => 1,
|
|
76
|
-
'body' => 'ZOMG A COMMENT'
|
|
77
|
-
}
|
|
78
|
-
],
|
|
79
|
-
'blog' => {
|
|
80
|
-
'id' => 999,
|
|
81
|
-
'name' => 'Custom blog'
|
|
82
|
-
},
|
|
83
|
-
'author' => {
|
|
84
|
-
'id' => 42,
|
|
85
|
-
'first_name' => 'Joao',
|
|
86
|
-
'last_name' => 'Moura'
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def assert_equal(expected, actual, message)
|
|
93
|
-
return true if expected == actual
|
|
94
|
-
if ENV['FAIL_ASSERTION'] =~ /\Atrue|on|0\z/i # rubocop:disable Style/GuardClause
|
|
95
|
-
fail BadRevisionError, message
|
|
96
|
-
else
|
|
97
|
-
STDERR.puts message unless ENV['SUMMARIZE']
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
assertion = ApiAssertion.new
|
|
102
|
-
assertion.valid?
|
|
103
|
-
assertion.debug { assertion.get_status }
|
|
104
|
-
|
|
105
|
-
time = 10
|
|
106
|
-
{
|
|
107
|
-
'caching on: caching serializers: gc off' => { disable_gc: true, send: [:get_caching, 'on'] },
|
|
108
|
-
'caching on: fragment caching serializers: gc off' => { disable_gc: true, send: [:get_fragment_caching, 'on'] },
|
|
109
|
-
'caching on: non-caching serializers: gc off' => { disable_gc: true, send: [:get_non_caching, 'on'] },
|
|
110
|
-
'caching off: caching serializers: gc off' => { disable_gc: true, send: [:get_caching, 'off'] },
|
|
111
|
-
'caching off: fragment caching serializers: gc off' => { disable_gc: true, send: [:get_fragment_caching, 'off'] },
|
|
112
|
-
'caching off: non-caching serializers: gc off' => { disable_gc: true, send: [:get_non_caching, 'off'] }
|
|
113
|
-
}.each do |label, options|
|
|
114
|
-
assertion.clear
|
|
115
|
-
Benchmark.ams(label, time: time, disable_gc: options[:disable_gc]) do
|
|
116
|
-
assertion.send(*options[:send])
|
|
117
|
-
end
|
|
118
|
-
assertion.debug { assertion.get_status(options[:send][-1]) }
|
|
119
|
-
end
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
require_relative './benchmarking_support'
|
|
2
|
-
require_relative './app'
|
|
3
|
-
|
|
4
|
-
time = 10
|
|
5
|
-
disable_gc = true
|
|
6
|
-
ActiveModelSerializers.config.key_transform = :unaltered
|
|
7
|
-
comments = (0..50).map do |i|
|
|
8
|
-
Comment.new(id: i, body: 'ZOMG A COMMENT')
|
|
9
|
-
end
|
|
10
|
-
author = Author.new(id: 42, first_name: 'Joao', last_name: 'Moura')
|
|
11
|
-
post = Post.new(id: 1337, title: 'New Post', blog: nil, body: 'Body', comments: comments, author: author)
|
|
12
|
-
serializer = PostSerializer.new(post)
|
|
13
|
-
adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
|
|
14
|
-
serialization = adapter.as_json
|
|
15
|
-
|
|
16
|
-
Benchmark.ams('camel', time: time, disable_gc: disable_gc) do
|
|
17
|
-
ActiveModelSerializers::KeyTransform.camel(serialization)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Benchmark.ams('camel_lower', time: time, disable_gc: disable_gc) do
|
|
21
|
-
ActiveModelSerializers::KeyTransform.camel_lower(serialization)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
Benchmark.ams('dash', time: time, disable_gc: disable_gc) do
|
|
25
|
-
ActiveModelSerializers::KeyTransform.dash(serialization)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
Benchmark.ams('unaltered', time: time, disable_gc: disable_gc) do
|
|
29
|
-
ActiveModelSerializers::KeyTransform.unaltered(serialization)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
Benchmark.ams('underscore', time: time, disable_gc: disable_gc) do
|
|
33
|
-
ActiveModelSerializers::KeyTransform.underscore(serialization)
|
|
34
|
-
end
|
data/test/benchmark/config.ru
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
class PostController < ActionController::Base
|
|
2
|
-
POST =
|
|
3
|
-
begin
|
|
4
|
-
updated_at = Time.current
|
|
5
|
-
if ENV['BENCH_STRESS']
|
|
6
|
-
comments = (0..50).map do |i|
|
|
7
|
-
Comment.new(id: i, body: 'ZOMG A COMMENT', updated_at: updated_at + i)
|
|
8
|
-
end
|
|
9
|
-
else
|
|
10
|
-
comments = [Comment.new(id: 1, body: 'ZOMG A COMMENT', updated_at: updated_at)]
|
|
11
|
-
end
|
|
12
|
-
author = Author.new(id: 42, first_name: 'Joao', last_name: 'Moura')
|
|
13
|
-
Post.new(id: 1337, title: 'New Post', blog: nil, body: 'Body', comments: comments, author: author)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def render_with_caching_serializer
|
|
17
|
-
toggle_cache_status
|
|
18
|
-
render json: POST, serializer: CachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def render_with_fragment_caching_serializer
|
|
22
|
-
toggle_cache_status
|
|
23
|
-
render json: POST, serializer: FragmentCachingPostSerializer, adapter: :json, meta: { caching: perform_caching }
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def render_with_non_caching_serializer
|
|
27
|
-
toggle_cache_status
|
|
28
|
-
render json: POST, adapter: :json, meta: { caching: perform_caching }
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def render_cache_status
|
|
32
|
-
toggle_cache_status
|
|
33
|
-
# Uncomment to debug
|
|
34
|
-
# STDERR.puts cache_store.class
|
|
35
|
-
# STDERR.puts cache_dependencies
|
|
36
|
-
# ActiveSupport::Cache::Store.logger.debug [ActiveModelSerializers.config.cache_store, ActiveModelSerializers.config.perform_caching, CachingPostSerializer._cache, perform_caching, params].inspect
|
|
37
|
-
render json: { caching: perform_caching, meta: { cache_log: cache_messages, cache_status: cache_status } }.to_json
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def clear
|
|
41
|
-
ActionController::Base.cache_store.clear
|
|
42
|
-
# Test caching is on
|
|
43
|
-
# Uncomment to turn on logger; possible performance issue
|
|
44
|
-
# logger = BenchmarkLogger.new
|
|
45
|
-
# ActiveSupport::Cache::Store.logger = logger # seems to be the best way
|
|
46
|
-
#
|
|
47
|
-
# the below is used in some rails tests but isn't available/working in all versions, so far as I can tell
|
|
48
|
-
# https://github.com/rails/rails/pull/15943
|
|
49
|
-
# ActiveSupport::Notifications.subscribe(/^cache_(.*)\.active_support$/) do |*args|
|
|
50
|
-
# logger.debug ActiveSupport::Notifications::Event.new(*args)
|
|
51
|
-
# end
|
|
52
|
-
render json: 'ok'.to_json
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
private
|
|
56
|
-
|
|
57
|
-
def cache_status
|
|
58
|
-
{
|
|
59
|
-
controller: perform_caching,
|
|
60
|
-
app: Rails.configuration.action_controller.perform_caching,
|
|
61
|
-
serializers: Rails.configuration.serializers.each_with_object({}) { |serializer, data| data[serializer.name] = serializer._cache.present? }
|
|
62
|
-
}
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def cache_messages
|
|
66
|
-
ActiveSupport::Cache::Store.logger.is_a?(BenchmarkLogger) && ActiveSupport::Cache::Store.logger.messages.split("\n")
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def toggle_cache_status
|
|
70
|
-
case params[:on]
|
|
71
|
-
when 'on'.freeze then self.perform_caching = true
|
|
72
|
-
when 'off'.freeze then self.perform_caching = false
|
|
73
|
-
else nil # no-op
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
Rails.application.routes.draw do
|
|
79
|
-
get '/status(/:on)' => 'post#render_cache_status'
|
|
80
|
-
get '/clear' => 'post#clear'
|
|
81
|
-
get '/caching(/:on)' => 'post#render_with_caching_serializer'
|
|
82
|
-
get '/fragment_caching(/:on)' => 'post#render_with_fragment_caching_serializer'
|
|
83
|
-
get '/non_caching(/:on)' => 'post#render_with_non_caching_serializer'
|
|
84
|
-
end
|