active_model_serializers 0.8.3 → 0.10.0
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 +4 -4
- data/.github/ISSUE_TEMPLATE.md +29 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
- data/.gitignore +17 -0
- data/.rubocop.yml +104 -0
- data/.rubocop_todo.yml +167 -0
- data/.simplecov +110 -0
- data/.travis.yml +39 -24
- data/CHANGELOG.md +465 -6
- data/CONTRIBUTING.md +105 -0
- data/Gemfile +50 -1
- data/{MIT-LICENSE.txt → MIT-LICENSE} +3 -2
- data/README.md +102 -590
- data/Rakefile +93 -8
- data/active_model_serializers.gemspec +65 -23
- data/appveyor.yml +24 -0
- data/bin/bench +171 -0
- data/bin/bench_regression +316 -0
- data/bin/serve_benchmark +39 -0
- data/docs/ARCHITECTURE.md +126 -0
- data/docs/README.md +40 -0
- data/docs/STYLE.md +58 -0
- data/docs/general/adapters.md +245 -0
- data/docs/general/caching.md +52 -0
- data/docs/general/configuration_options.md +100 -0
- data/docs/general/deserialization.md +100 -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 +14 -0
- data/docs/general/rendering.md +255 -0
- data/docs/general/serializers.md +372 -0
- data/docs/how-open-source-maintained.jpg +0 -0
- data/docs/howto/add_pagination_links.md +139 -0
- data/docs/howto/add_root_key.md +51 -0
- data/docs/howto/outside_controller_use.md +58 -0
- data/docs/howto/passing_arbitrary_options.md +27 -0
- data/docs/howto/serialize_poro.md +32 -0
- data/docs/howto/test.md +152 -0
- data/docs/integrations/ember-and-json-api.md +112 -0
- data/docs/integrations/grape.md +19 -0
- data/docs/jsonapi/errors.md +56 -0
- data/docs/jsonapi/schema/schema.json +366 -0
- data/docs/jsonapi/schema.md +151 -0
- data/docs/rfcs/0000-namespace.md +106 -0
- data/docs/rfcs/template.md +15 -0
- data/lib/action_controller/serialization.rb +31 -36
- data/lib/active_model/serializable_resource.rb +11 -0
- data/lib/active_model/serializer/adapter/attributes.rb +15 -0
- data/lib/active_model/serializer/adapter/base.rb +16 -0
- data/lib/active_model/serializer/adapter/json.rb +15 -0
- data/lib/active_model/serializer/adapter/json_api.rb +15 -0
- data/lib/active_model/serializer/adapter/null.rb +15 -0
- data/lib/active_model/serializer/adapter.rb +24 -0
- data/lib/active_model/serializer/array_serializer.rb +9 -0
- data/lib/active_model/serializer/association.rb +19 -0
- data/lib/active_model/serializer/associations.rb +87 -220
- data/lib/active_model/serializer/attribute.rb +25 -0
- data/lib/active_model/serializer/attributes.rb +82 -0
- data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
- data/lib/active_model/serializer/caching.rb +333 -0
- data/lib/active_model/serializer/collection_reflection.rb +7 -0
- data/lib/active_model/serializer/collection_serializer.rb +64 -0
- data/lib/active_model/serializer/configuration.rb +35 -0
- data/lib/active_model/serializer/error_serializer.rb +10 -0
- data/lib/active_model/serializer/errors_serializer.rb +27 -0
- data/lib/active_model/serializer/field.rb +90 -0
- data/lib/active_model/serializer/fieldset.rb +31 -0
- data/lib/active_model/serializer/has_many_reflection.rb +10 -0
- data/lib/active_model/serializer/has_one_reflection.rb +10 -0
- data/lib/active_model/serializer/include_tree.rb +111 -0
- data/lib/active_model/serializer/links.rb +35 -0
- data/lib/active_model/serializer/lint.rb +146 -0
- data/lib/active_model/serializer/meta.rb +29 -0
- data/lib/active_model/serializer/null.rb +17 -0
- data/lib/active_model/serializer/reflection.rb +147 -0
- data/lib/active_model/serializer/singular_reflection.rb +7 -0
- data/lib/active_model/serializer/type.rb +25 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +158 -481
- data/lib/active_model_serializers/adapter/attributes.rb +76 -0
- data/lib/active_model_serializers/adapter/base.rb +83 -0
- data/lib/active_model_serializers/adapter/json.rb +21 -0
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
- data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
- data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
- data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
- data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +62 -0
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +52 -0
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +37 -0
- data/lib/active_model_serializers/adapter/json_api.rb +516 -0
- data/lib/active_model_serializers/adapter/null.rb +9 -0
- data/lib/active_model_serializers/adapter.rb +92 -0
- data/lib/active_model_serializers/callbacks.rb +55 -0
- data/lib/active_model_serializers/deprecate.rb +55 -0
- data/lib/active_model_serializers/deserialization.rb +13 -0
- data/lib/active_model_serializers/json_pointer.rb +14 -0
- data/lib/active_model_serializers/key_transform.rb +70 -0
- data/lib/active_model_serializers/logging.rb +122 -0
- data/lib/active_model_serializers/model.rb +49 -0
- data/lib/active_model_serializers/railtie.rb +46 -0
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +65 -0
- data/lib/active_model_serializers/serializable_resource.rb +81 -0
- data/lib/active_model_serializers/serialization_context.rb +32 -0
- data/lib/active_model_serializers/test/schema.rb +138 -0
- data/lib/active_model_serializers/test/serializer.rb +125 -0
- data/lib/active_model_serializers/test.rb +7 -0
- data/lib/active_model_serializers.rb +32 -89
- data/lib/generators/rails/USAGE +6 -0
- data/lib/generators/rails/resource_override.rb +10 -0
- data/lib/generators/rails/serializer_generator.rb +36 -0
- data/lib/generators/rails/templates/serializer.rb.erb +8 -0
- data/lib/grape/active_model_serializers.rb +14 -0
- data/lib/grape/formatters/active_model_serializers.rb +15 -0
- data/lib/grape/helpers/active_model_serializers.rb +16 -0
- data/test/action_controller/adapter_selector_test.rb +53 -0
- data/test/action_controller/explicit_serializer_test.rb +134 -0
- data/test/action_controller/json/include_test.rb +167 -0
- data/test/action_controller/json_api/deserialization_test.rb +112 -0
- data/test/action_controller/json_api/errors_test.rb +41 -0
- data/test/action_controller/json_api/linked_test.rb +197 -0
- data/test/action_controller/json_api/pagination_test.rb +116 -0
- data/test/action_controller/json_api/transform_test.rb +181 -0
- data/test/action_controller/serialization_scope_name_test.rb +229 -0
- data/test/action_controller/serialization_test.rb +469 -0
- data/test/active_model_serializers/adapter_for_test.rb +208 -0
- data/test/active_model_serializers/json_pointer_test.rb +20 -0
- data/test/active_model_serializers/key_transform_test.rb +263 -0
- data/test/active_model_serializers/logging_test.rb +77 -0
- data/test/active_model_serializers/model_test.rb +9 -0
- data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +58 -0
- data/test/active_model_serializers/test/schema_test.rb +130 -0
- data/test/active_model_serializers/test/serializer_test.rb +62 -0
- data/test/active_record_test.rb +9 -0
- data/test/adapter/deprecation_test.rb +100 -0
- data/test/adapter/json/belongs_to_test.rb +45 -0
- data/test/adapter/json/collection_test.rb +90 -0
- data/test/adapter/json/has_many_test.rb +45 -0
- data/test/adapter/json/transform_test.rb +93 -0
- data/test/adapter/json_api/belongs_to_test.rb +155 -0
- data/test/adapter/json_api/collection_test.rb +95 -0
- data/test/adapter/json_api/errors_test.rb +78 -0
- data/test/adapter/json_api/fields_test.rb +87 -0
- data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
- data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
- data/test/adapter/json_api/has_many_test.rb +144 -0
- data/test/adapter/json_api/has_one_test.rb +80 -0
- data/test/adapter/json_api/json_api_test.rb +35 -0
- data/test/adapter/json_api/linked_test.rb +392 -0
- data/test/adapter/json_api/links_test.rb +93 -0
- data/test/adapter/json_api/pagination_links_test.rb +166 -0
- data/test/adapter/json_api/parse_test.rb +137 -0
- data/test/adapter/json_api/relationship_test.rb +161 -0
- data/test/adapter/json_api/relationships_test.rb +199 -0
- data/test/adapter/json_api/resource_identifier_test.rb +85 -0
- data/test/adapter/json_api/resource_meta_test.rb +100 -0
- data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
- data/test/adapter/json_api/transform_test.rb +502 -0
- data/test/adapter/json_api/type_test.rb +61 -0
- data/test/adapter/json_test.rb +45 -0
- data/test/adapter/null_test.rb +23 -0
- data/test/adapter/polymorphic_test.rb +171 -0
- data/test/adapter_test.rb +67 -0
- data/test/array_serializer_test.rb +20 -73
- data/test/benchmark/app.rb +65 -0
- data/test/benchmark/benchmarking_support.rb +67 -0
- data/test/benchmark/bm_caching.rb +119 -0
- data/test/benchmark/bm_transform.rb +34 -0
- data/test/benchmark/config.ru +3 -0
- data/test/benchmark/controllers.rb +84 -0
- data/test/benchmark/fixtures.rb +219 -0
- data/test/cache_test.rb +485 -0
- data/test/collection_serializer_test.rb +110 -0
- data/test/fixtures/active_record.rb +78 -0
- data/test/fixtures/poro.rb +282 -0
- data/test/generators/scaffold_controller_generator_test.rb +24 -0
- data/test/generators/serializer_generator_test.rb +57 -0
- data/test/grape_test.rb +82 -0
- data/test/include_tree/from_include_args_test.rb +26 -0
- data/test/include_tree/from_string_test.rb +94 -0
- data/test/include_tree/include_args_to_hash_test.rb +64 -0
- data/test/lint_test.rb +49 -0
- data/test/logger_test.rb +18 -0
- data/test/poro_test.rb +9 -0
- data/test/serializable_resource_test.rb +83 -0
- data/test/serializers/association_macros_test.rb +36 -0
- data/test/serializers/associations_test.rb +295 -0
- data/test/serializers/attribute_test.rb +151 -0
- data/test/serializers/attributes_test.rb +52 -0
- data/test/serializers/caching_configuration_test_isolated.rb +170 -0
- data/test/serializers/configuration_test.rb +32 -0
- data/test/serializers/fieldset_test.rb +14 -0
- data/test/serializers/meta_test.rb +196 -0
- data/test/serializers/options_test.rb +21 -0
- data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
- data/test/serializers/root_test.rb +21 -0
- data/test/serializers/serialization_test.rb +55 -0
- data/test/serializers/serializer_for_test.rb +134 -0
- data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
- data/test/support/isolated_unit.rb +79 -0
- data/test/support/rails5_shims.rb +47 -0
- data/test/support/rails_app.rb +45 -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 +53 -0
- data/test/test_helper.rb +48 -23
- metadata +449 -43
- data/DESIGN.textile +0 -586
- data/Gemfile.edge +0 -9
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_model/array_serializer.rb +0 -104
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/USAGE +0 -9
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class ExplicitSerializerTest < ActionController::TestCase
|
|
6
|
+
class ExplicitSerializerTestController < ActionController::Base
|
|
7
|
+
def render_using_explicit_serializer
|
|
8
|
+
@profile = Profile.new(name: 'Name 1',
|
|
9
|
+
description: 'Description 1',
|
|
10
|
+
comments: 'Comments 1')
|
|
11
|
+
render json: @profile, serializer: ProfilePreviewSerializer
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render_array_using_explicit_serializer
|
|
15
|
+
array = [
|
|
16
|
+
Profile.new(name: 'Name 1',
|
|
17
|
+
description: 'Description 1',
|
|
18
|
+
comments: 'Comments 1'),
|
|
19
|
+
Profile.new(name: 'Name 2',
|
|
20
|
+
description: 'Description 2',
|
|
21
|
+
comments: 'Comments 2')
|
|
22
|
+
]
|
|
23
|
+
render json: array,
|
|
24
|
+
serializer: PaginatedSerializer,
|
|
25
|
+
each_serializer: ProfilePreviewSerializer
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def render_array_using_implicit_serializer
|
|
29
|
+
array = [
|
|
30
|
+
Profile.new(name: 'Name 1',
|
|
31
|
+
description: 'Description 1',
|
|
32
|
+
comments: 'Comments 1'),
|
|
33
|
+
Profile.new(name: 'Name 2',
|
|
34
|
+
description: 'Description 2',
|
|
35
|
+
comments: 'Comments 2')
|
|
36
|
+
]
|
|
37
|
+
render json: array,
|
|
38
|
+
each_serializer: ProfilePreviewSerializer
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def render_array_using_explicit_serializer_and_custom_serializers
|
|
42
|
+
@post = Post.new(title: 'New Post', body: 'Body')
|
|
43
|
+
@author = Author.new(name: 'Jane Blogger')
|
|
44
|
+
@author.posts = [@post]
|
|
45
|
+
@post.author = @author
|
|
46
|
+
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
47
|
+
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
48
|
+
@post.comments = [@first_comment, @second_comment]
|
|
49
|
+
@first_comment.post = @post
|
|
50
|
+
@first_comment.author = nil
|
|
51
|
+
@second_comment.post = @post
|
|
52
|
+
@second_comment.author = nil
|
|
53
|
+
@blog = Blog.new(id: 23, name: 'AMS Blog')
|
|
54
|
+
@post.blog = @blog
|
|
55
|
+
|
|
56
|
+
render json: [@post], each_serializer: PostPreviewSerializer
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def render_using_explicit_each_serializer
|
|
60
|
+
location = Location.new(id: 42, lat: '-23.550520', lng: '-46.633309')
|
|
61
|
+
place = Place.new(id: 1337, name: 'Amazing Place', locations: [location])
|
|
62
|
+
|
|
63
|
+
render json: place, each_serializer: PlaceSerializer
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
tests ExplicitSerializerTestController
|
|
68
|
+
|
|
69
|
+
def test_render_using_explicit_serializer
|
|
70
|
+
get :render_using_explicit_serializer
|
|
71
|
+
|
|
72
|
+
assert_equal 'application/json', @response.content_type
|
|
73
|
+
assert_equal '{"name":"Name 1"}', @response.body
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_render_array_using_explicit_serializer
|
|
77
|
+
get :render_array_using_explicit_serializer
|
|
78
|
+
assert_equal 'application/json', @response.content_type
|
|
79
|
+
|
|
80
|
+
expected = [
|
|
81
|
+
{ 'name' => 'Name 1' },
|
|
82
|
+
{ 'name' => 'Name 2' }
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
assert_equal expected.to_json, @response.body
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_render_array_using_implicit_serializer
|
|
89
|
+
get :render_array_using_implicit_serializer
|
|
90
|
+
assert_equal 'application/json', @response.content_type
|
|
91
|
+
|
|
92
|
+
expected = [
|
|
93
|
+
{ 'name' => 'Name 1' },
|
|
94
|
+
{ 'name' => 'Name 2' }
|
|
95
|
+
]
|
|
96
|
+
assert_equal expected.to_json, @response.body
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_render_array_using_explicit_serializer_and_custom_serializers
|
|
100
|
+
get :render_array_using_explicit_serializer_and_custom_serializers
|
|
101
|
+
|
|
102
|
+
expected = [
|
|
103
|
+
{ 'title' => 'New Post',
|
|
104
|
+
'body' => 'Body',
|
|
105
|
+
'id' => assigns(:post).id,
|
|
106
|
+
'comments' => [{ 'id' => 1 }, { 'id' => 2 }],
|
|
107
|
+
'author' => { 'id' => assigns(:author).id }
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
assert_equal expected.to_json, @response.body
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_render_using_explicit_each_serializer
|
|
115
|
+
get :render_using_explicit_each_serializer
|
|
116
|
+
|
|
117
|
+
expected = {
|
|
118
|
+
id: 1337,
|
|
119
|
+
name: 'Amazing Place',
|
|
120
|
+
locations: [
|
|
121
|
+
{
|
|
122
|
+
id: 42,
|
|
123
|
+
lat: '-23.550520',
|
|
124
|
+
lng: '-46.633309',
|
|
125
|
+
place: 'Nowhere' # is a virtual attribute on LocationSerializer
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
assert_equal expected.to_json, response.body
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class Json
|
|
6
|
+
class IncludeTest < ActionController::TestCase
|
|
7
|
+
class IncludeTestController < ActionController::Base
|
|
8
|
+
def setup_data
|
|
9
|
+
ActionController::Base.cache_store.clear
|
|
10
|
+
|
|
11
|
+
@author = Author.new(id: 1, name: 'Steve K.')
|
|
12
|
+
|
|
13
|
+
@post = Post.new(id: 42, title: 'New Post', body: 'Body')
|
|
14
|
+
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
15
|
+
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
16
|
+
|
|
17
|
+
@post.comments = [@first_comment, @second_comment]
|
|
18
|
+
@post.author = @author
|
|
19
|
+
|
|
20
|
+
@first_comment.post = @post
|
|
21
|
+
@second_comment.post = @post
|
|
22
|
+
|
|
23
|
+
@blog = Blog.new(id: 1, name: 'My Blog!!')
|
|
24
|
+
@post.blog = @blog
|
|
25
|
+
@author.posts = [@post]
|
|
26
|
+
|
|
27
|
+
@first_comment.author = @author
|
|
28
|
+
@second_comment.author = @author
|
|
29
|
+
@author.comments = [@first_comment, @second_comment]
|
|
30
|
+
@author.roles = []
|
|
31
|
+
@author.bio = {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render_without_include
|
|
35
|
+
setup_data
|
|
36
|
+
render json: @author, adapter: :json
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def render_resource_with_include_hash
|
|
40
|
+
setup_data
|
|
41
|
+
render json: @author, include: { posts: :comments }, adapter: :json
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def render_resource_with_include_string
|
|
45
|
+
setup_data
|
|
46
|
+
render json: @author, include: 'posts.comments', adapter: :json
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def render_resource_with_deep_include
|
|
50
|
+
setup_data
|
|
51
|
+
render json: @author, include: 'posts.comments.author', adapter: :json
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
tests IncludeTestController
|
|
56
|
+
|
|
57
|
+
def test_render_without_include
|
|
58
|
+
get :render_without_include
|
|
59
|
+
response = JSON.parse(@response.body)
|
|
60
|
+
expected = {
|
|
61
|
+
'author' => {
|
|
62
|
+
'id' => 1,
|
|
63
|
+
'name' => 'Steve K.',
|
|
64
|
+
'posts' => [
|
|
65
|
+
{
|
|
66
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body'
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
'roles' => [],
|
|
70
|
+
'bio' => {}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
assert_equal(expected, response)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_render_resource_with_include_hash
|
|
78
|
+
get :render_resource_with_include_hash
|
|
79
|
+
response = JSON.parse(@response.body)
|
|
80
|
+
expected = {
|
|
81
|
+
'author' => {
|
|
82
|
+
'id' => 1,
|
|
83
|
+
'name' => 'Steve K.',
|
|
84
|
+
'posts' => [
|
|
85
|
+
{
|
|
86
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body',
|
|
87
|
+
'comments' => [
|
|
88
|
+
{
|
|
89
|
+
'id' => 1, 'body' => 'ZOMG A COMMENT'
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
'id' => 2, 'body' => 'ZOMG ANOTHER COMMENT'
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
assert_equal(expected, response)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_render_resource_with_include_string
|
|
104
|
+
get :render_resource_with_include_string
|
|
105
|
+
|
|
106
|
+
response = JSON.parse(@response.body)
|
|
107
|
+
expected = {
|
|
108
|
+
'author' => {
|
|
109
|
+
'id' => 1,
|
|
110
|
+
'name' => 'Steve K.',
|
|
111
|
+
'posts' => [
|
|
112
|
+
{
|
|
113
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body',
|
|
114
|
+
'comments' => [
|
|
115
|
+
{
|
|
116
|
+
'id' => 1, 'body' => 'ZOMG A COMMENT'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
'id' => 2, 'body' => 'ZOMG ANOTHER COMMENT'
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
assert_equal(expected, response)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_render_resource_with_deep_include
|
|
131
|
+
get :render_resource_with_deep_include
|
|
132
|
+
|
|
133
|
+
response = JSON.parse(@response.body)
|
|
134
|
+
expected = {
|
|
135
|
+
'author' => {
|
|
136
|
+
'id' => 1,
|
|
137
|
+
'name' => 'Steve K.',
|
|
138
|
+
'posts' => [
|
|
139
|
+
{
|
|
140
|
+
'id' => 42, 'title' => 'New Post', 'body' => 'Body',
|
|
141
|
+
'comments' => [
|
|
142
|
+
{
|
|
143
|
+
'id' => 1, 'body' => 'ZOMG A COMMENT',
|
|
144
|
+
'author' => {
|
|
145
|
+
'id' => 1,
|
|
146
|
+
'name' => 'Steve K.'
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
'id' => 2, 'body' => 'ZOMG ANOTHER COMMENT',
|
|
151
|
+
'author' => {
|
|
152
|
+
'id' => 1,
|
|
153
|
+
'name' => 'Steve K.'
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
assert_equal(expected, response)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class JsonApi
|
|
6
|
+
class DeserializationTest < ActionController::TestCase
|
|
7
|
+
class DeserializationTestController < ActionController::Base
|
|
8
|
+
def render_parsed_payload
|
|
9
|
+
parsed_hash = ActiveModelSerializers::Deserialization.jsonapi_parse(params)
|
|
10
|
+
render json: parsed_hash
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def render_polymorphic_parsed_payload
|
|
14
|
+
parsed_hash = ActiveModelSerializers::Deserialization.jsonapi_parse(
|
|
15
|
+
params,
|
|
16
|
+
polymorphic: [:restriction_for, :restricted_to]
|
|
17
|
+
)
|
|
18
|
+
render json: parsed_hash
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
tests DeserializationTestController
|
|
23
|
+
|
|
24
|
+
def test_deserialization_of_relationship_only_object
|
|
25
|
+
hash = {
|
|
26
|
+
'data' => {
|
|
27
|
+
'type' => 'restraints',
|
|
28
|
+
'relationships' => {
|
|
29
|
+
'restriction_for' => {
|
|
30
|
+
'data' => {
|
|
31
|
+
'type' => 'discounts',
|
|
32
|
+
'id' => '67'
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
'restricted_to' => {
|
|
36
|
+
'data' => nil
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
'restraint' => {}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
post :render_polymorphic_parsed_payload, params: hash
|
|
44
|
+
|
|
45
|
+
response = JSON.parse(@response.body)
|
|
46
|
+
expected = {
|
|
47
|
+
'restriction_for_id' => '67',
|
|
48
|
+
'restriction_for_type' => 'discounts',
|
|
49
|
+
'restricted_to_id' => nil,
|
|
50
|
+
'restricted_to_type' => nil
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assert_equal(expected, response)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def test_deserialization
|
|
57
|
+
hash = {
|
|
58
|
+
'data' => {
|
|
59
|
+
'type' => 'photos',
|
|
60
|
+
'id' => 'zorglub',
|
|
61
|
+
'attributes' => {
|
|
62
|
+
'title' => 'Ember Hamster',
|
|
63
|
+
'src' => 'http://example.com/images/productivity.png',
|
|
64
|
+
'image-width' => '200',
|
|
65
|
+
'imageHeight' => '200',
|
|
66
|
+
'ImageSize' => '1024'
|
|
67
|
+
},
|
|
68
|
+
'relationships' => {
|
|
69
|
+
'author' => {
|
|
70
|
+
'data' => nil
|
|
71
|
+
},
|
|
72
|
+
'photographer' => {
|
|
73
|
+
'data' => { 'type' => 'people', 'id' => '9' }
|
|
74
|
+
},
|
|
75
|
+
'comments' => {
|
|
76
|
+
'data' => [
|
|
77
|
+
{ 'type' => 'comments', 'id' => '1' },
|
|
78
|
+
{ 'type' => 'comments', 'id' => '2' }
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
'related-images' => {
|
|
82
|
+
'data' => [
|
|
83
|
+
{ 'type' => 'image', 'id' => '7' },
|
|
84
|
+
{ 'type' => 'image', 'id' => '8' }
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
post :render_parsed_payload, params: hash
|
|
92
|
+
|
|
93
|
+
response = JSON.parse(@response.body)
|
|
94
|
+
expected = {
|
|
95
|
+
'id' => 'zorglub',
|
|
96
|
+
'title' => 'Ember Hamster',
|
|
97
|
+
'src' => 'http://example.com/images/productivity.png',
|
|
98
|
+
'image_width' => '200',
|
|
99
|
+
'image_height' => '200',
|
|
100
|
+
'image_size' => '1024',
|
|
101
|
+
'author_id' => nil,
|
|
102
|
+
'photographer_id' => '9',
|
|
103
|
+
'comment_ids' => %w(1 2),
|
|
104
|
+
'related_image_ids' => %w(7 8)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
assert_equal(expected, response)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class JsonApi
|
|
6
|
+
class ErrorsTest < ActionController::TestCase
|
|
7
|
+
def test_active_model_with_multiple_errors
|
|
8
|
+
get :render_resource_with_errors
|
|
9
|
+
|
|
10
|
+
expected_errors_object =
|
|
11
|
+
{ :errors =>
|
|
12
|
+
[
|
|
13
|
+
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'cannot be nil' },
|
|
14
|
+
{ :source => { :pointer => '/data/attributes/name' }, :detail => 'must be longer' },
|
|
15
|
+
{ :source => { :pointer => '/data/attributes/id' }, :detail => 'must be a uuid' }
|
|
16
|
+
]
|
|
17
|
+
}.to_json
|
|
18
|
+
assert_equal json_reponse_body.to_json, expected_errors_object
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def json_reponse_body
|
|
22
|
+
JSON.load(@response.body)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class ErrorsTestController < ActionController::Base
|
|
26
|
+
def render_resource_with_errors
|
|
27
|
+
resource = Profile.new(name: 'Name 1',
|
|
28
|
+
description: 'Description 1',
|
|
29
|
+
comments: 'Comments 1')
|
|
30
|
+
resource.errors.add(:name, 'cannot be nil')
|
|
31
|
+
resource.errors.add(:name, 'must be longer')
|
|
32
|
+
resource.errors.add(:id, 'must be a uuid')
|
|
33
|
+
render json: resource, adapter: :json_api, serializer: ActiveModel::Serializer::ErrorSerializer
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
tests ErrorsTestController
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class JsonApi
|
|
6
|
+
class LinkedTest < ActionController::TestCase
|
|
7
|
+
class LinkedTestController < ActionController::Base
|
|
8
|
+
require 'active_model_serializers/register_jsonapi_renderer'
|
|
9
|
+
def setup_post
|
|
10
|
+
ActionController::Base.cache_store.clear
|
|
11
|
+
@role1 = Role.new(id: 1, name: 'admin')
|
|
12
|
+
@role2 = Role.new(id: 2, name: 'colab')
|
|
13
|
+
@author = Author.new(id: 1, name: 'Steve K.')
|
|
14
|
+
@author.posts = []
|
|
15
|
+
@author.bio = nil
|
|
16
|
+
@author.roles = [@role1, @role2]
|
|
17
|
+
@role1.author = @author
|
|
18
|
+
@role2.author = @author
|
|
19
|
+
@author2 = Author.new(id: 2, name: 'Anonymous')
|
|
20
|
+
@author2.posts = []
|
|
21
|
+
@author2.bio = nil
|
|
22
|
+
@author2.roles = []
|
|
23
|
+
@post = Post.new(id: 1, title: 'New Post', body: 'Body')
|
|
24
|
+
@first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
|
|
25
|
+
@second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
|
|
26
|
+
@post.comments = [@first_comment, @second_comment]
|
|
27
|
+
@post.author = @author
|
|
28
|
+
@first_comment.post = @post
|
|
29
|
+
@first_comment.author = @author2
|
|
30
|
+
@second_comment.post = @post
|
|
31
|
+
@second_comment.author = nil
|
|
32
|
+
@post2 = Post.new(id: 2, title: 'Another Post', body: 'Body')
|
|
33
|
+
@post2.author = @author
|
|
34
|
+
@post2.comments = []
|
|
35
|
+
@blog = Blog.new(id: 1, name: 'My Blog!!')
|
|
36
|
+
@post.blog = @blog
|
|
37
|
+
@post2.blog = @blog
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def render_resource_without_include
|
|
41
|
+
setup_post
|
|
42
|
+
render jsonapi: @post
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def render_resource_with_include
|
|
46
|
+
setup_post
|
|
47
|
+
render jsonapi: @post, include: [:author]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def render_resource_with_include_of_custom_key_by_original
|
|
51
|
+
setup_post
|
|
52
|
+
render jsonapi: @post, include: [:reviews], serializer: PostWithCustomKeysSerializer
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def render_resource_with_nested_include
|
|
56
|
+
setup_post
|
|
57
|
+
render jsonapi: @post, include: [comments: [:author]]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def render_resource_with_nested_has_many_include_wildcard
|
|
61
|
+
setup_post
|
|
62
|
+
render jsonapi: @post, include: 'author.*'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def render_resource_with_missing_nested_has_many_include
|
|
66
|
+
setup_post
|
|
67
|
+
@post.author = @author2 # author2 has no roles.
|
|
68
|
+
render jsonapi: @post, include: [author: [:roles]]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def render_collection_with_missing_nested_has_many_include
|
|
72
|
+
setup_post
|
|
73
|
+
@post.author = @author2
|
|
74
|
+
render jsonapi: [@post, @post2], include: [author: [:roles]]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def render_collection_without_include
|
|
78
|
+
setup_post
|
|
79
|
+
render jsonapi: [@post]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def render_collection_with_include
|
|
83
|
+
setup_post
|
|
84
|
+
render jsonapi: [@post], include: 'author, comments'
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
tests LinkedTestController
|
|
89
|
+
|
|
90
|
+
def test_render_resource_without_include
|
|
91
|
+
get :render_resource_without_include
|
|
92
|
+
response = JSON.parse(@response.body)
|
|
93
|
+
refute response.key? 'included'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_render_resource_with_include
|
|
97
|
+
get :render_resource_with_include
|
|
98
|
+
response = JSON.parse(@response.body)
|
|
99
|
+
assert response.key? 'included'
|
|
100
|
+
assert_equal 1, response['included'].size
|
|
101
|
+
assert_equal 'Steve K.', response['included'].first['attributes']['name']
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def test_render_resource_with_nested_has_many_include
|
|
105
|
+
get :render_resource_with_nested_has_many_include_wildcard
|
|
106
|
+
response = JSON.parse(@response.body)
|
|
107
|
+
expected_linked = [
|
|
108
|
+
{
|
|
109
|
+
'id' => '1',
|
|
110
|
+
'type' => 'authors',
|
|
111
|
+
'attributes' => {
|
|
112
|
+
'name' => 'Steve K.'
|
|
113
|
+
},
|
|
114
|
+
'relationships' => {
|
|
115
|
+
'posts' => { 'data' => [] },
|
|
116
|
+
'roles' => { 'data' => [{ 'type' => 'roles', 'id' => '1' }, { 'type' => 'roles', 'id' => '2' }] },
|
|
117
|
+
'bio' => { 'data' => nil }
|
|
118
|
+
}
|
|
119
|
+
}, {
|
|
120
|
+
'id' => '1',
|
|
121
|
+
'type' => 'roles',
|
|
122
|
+
'attributes' => {
|
|
123
|
+
'name' => 'admin',
|
|
124
|
+
'description' => nil,
|
|
125
|
+
'slug' => 'admin-1'
|
|
126
|
+
},
|
|
127
|
+
'relationships' => {
|
|
128
|
+
'author' => { 'data' => { 'type' => 'authors', 'id' => '1' } }
|
|
129
|
+
}
|
|
130
|
+
}, {
|
|
131
|
+
'id' => '2',
|
|
132
|
+
'type' => 'roles',
|
|
133
|
+
'attributes' => {
|
|
134
|
+
'name' => 'colab',
|
|
135
|
+
'description' => nil,
|
|
136
|
+
'slug' => 'colab-2'
|
|
137
|
+
},
|
|
138
|
+
'relationships' => {
|
|
139
|
+
'author' => { 'data' => { 'type' => 'authors', 'id' => '1' } }
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
assert_equal expected_linked, response['included']
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_render_resource_with_include_of_custom_key_by_original
|
|
147
|
+
get :render_resource_with_include_of_custom_key_by_original
|
|
148
|
+
response = JSON.parse(@response.body)
|
|
149
|
+
assert response.key? 'included'
|
|
150
|
+
|
|
151
|
+
relationships = response['data']['relationships']
|
|
152
|
+
|
|
153
|
+
assert_includes relationships, 'reviews'
|
|
154
|
+
assert_includes relationships, 'writer'
|
|
155
|
+
assert_includes relationships, 'site'
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def test_render_resource_with_nested_include
|
|
159
|
+
get :render_resource_with_nested_include
|
|
160
|
+
response = JSON.parse(@response.body)
|
|
161
|
+
assert response.key? 'included'
|
|
162
|
+
assert_equal 3, response['included'].size
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def test_render_collection_without_include
|
|
166
|
+
get :render_collection_without_include
|
|
167
|
+
response = JSON.parse(@response.body)
|
|
168
|
+
refute response.key? 'included'
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_render_collection_with_include
|
|
172
|
+
get :render_collection_with_include
|
|
173
|
+
response = JSON.parse(@response.body)
|
|
174
|
+
assert response.key? 'included'
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_render_resource_with_nested_attributes_even_when_missing_associations
|
|
178
|
+
get :render_resource_with_missing_nested_has_many_include
|
|
179
|
+
response = JSON.parse(@response.body)
|
|
180
|
+
assert response.key? 'included'
|
|
181
|
+
refute has_type?(response['included'], 'roles')
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_render_collection_with_missing_nested_has_many_include
|
|
185
|
+
get :render_collection_with_missing_nested_has_many_include
|
|
186
|
+
response = JSON.parse(@response.body)
|
|
187
|
+
assert response.key? 'included'
|
|
188
|
+
assert has_type?(response['included'], 'roles')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def has_type?(collection, value)
|
|
192
|
+
collection.detect { |i| i['type'] == value }
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|