active_model_serializers 0.10.0 → 0.10.7
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/.rubocop.yml +6 -5
- data/.travis.yml +30 -21
- data/CHANGELOG.md +172 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +23 -4
- data/README.md +166 -28
- data/Rakefile +3 -32
- data/active_model_serializers.gemspec +22 -25
- data/appveyor.yml +10 -6
- data/bin/rubocop +38 -0
- data/docs/README.md +2 -1
- data/docs/general/adapters.md +35 -11
- data/docs/general/caching.md +7 -1
- data/docs/general/configuration_options.md +86 -1
- data/docs/general/deserialization.md +1 -1
- data/docs/general/fields.md +31 -0
- data/docs/general/getting_started.md +1 -1
- data/docs/general/logging.md +7 -0
- data/docs/general/rendering.md +63 -25
- data/docs/general/serializers.md +125 -14
- data/docs/howto/add_pagination_links.md +16 -17
- data/docs/howto/add_relationship_links.md +140 -0
- data/docs/howto/add_root_key.md +11 -0
- data/docs/howto/grape_integration.md +42 -0
- data/docs/howto/outside_controller_use.md +12 -4
- data/docs/howto/passing_arbitrary_options.md +2 -2
- data/docs/howto/serialize_poro.md +46 -5
- data/docs/howto/test.md +2 -0
- data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
- data/docs/integrations/ember-and-json-api.md +67 -32
- data/docs/jsonapi/schema.md +1 -1
- data/lib/action_controller/serialization.rb +13 -3
- data/lib/active_model/serializer/adapter/base.rb +2 -0
- data/lib/active_model/serializer/array_serializer.rb +8 -5
- data/lib/active_model/serializer/association.rb +62 -10
- data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
- data/lib/active_model/serializer/collection_serializer.rb +39 -13
- data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
- data/lib/active_model/serializer/error_serializer.rb +11 -7
- data/lib/active_model/serializer/errors_serializer.rb +25 -20
- data/lib/active_model/serializer/has_many_reflection.rb +3 -3
- data/lib/active_model/serializer/has_one_reflection.rb +1 -4
- data/lib/active_model/serializer/lazy_association.rb +95 -0
- data/lib/active_model/serializer/lint.rb +134 -130
- data/lib/active_model/serializer/reflection.rb +127 -67
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model/serializer.rb +297 -79
- data/lib/active_model_serializers/adapter/attributes.rb +3 -66
- data/lib/active_model_serializers/adapter/base.rb +39 -39
- data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
- data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +47 -21
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
- data/lib/active_model_serializers/adapter/json_api.rb +71 -57
- data/lib/active_model_serializers/adapter.rb +6 -0
- data/lib/active_model_serializers/deprecate.rb +1 -2
- data/lib/active_model_serializers/deserialization.rb +2 -0
- data/lib/active_model_serializers/lookup_chain.rb +80 -0
- data/lib/active_model_serializers/model.rb +109 -28
- data/lib/active_model_serializers/railtie.rb +3 -1
- data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
- data/lib/active_model_serializers/serializable_resource.rb +6 -5
- data/lib/active_model_serializers/serialization_context.rb +10 -3
- data/lib/active_model_serializers/test/schema.rb +2 -2
- data/lib/active_model_serializers.rb +16 -1
- data/lib/generators/rails/resource_override.rb +1 -1
- data/lib/generators/rails/serializer_generator.rb +4 -4
- data/lib/grape/active_model_serializers.rb +7 -5
- data/lib/grape/formatters/active_model_serializers.rb +19 -2
- data/lib/grape/helpers/active_model_serializers.rb +1 -0
- data/lib/tasks/rubocop.rake +53 -0
- data/test/action_controller/adapter_selector_test.rb +14 -5
- data/test/action_controller/explicit_serializer_test.rb +5 -4
- data/test/action_controller/json/include_test.rb +106 -27
- data/test/action_controller/json_api/deserialization_test.rb +1 -1
- data/test/action_controller/json_api/errors_test.rb +8 -9
- data/test/action_controller/json_api/fields_test.rb +66 -0
- data/test/action_controller/json_api/linked_test.rb +29 -24
- data/test/action_controller/json_api/pagination_test.rb +31 -23
- data/test/action_controller/json_api/transform_test.rb +11 -3
- data/test/action_controller/lookup_proc_test.rb +49 -0
- data/test/action_controller/namespace_lookup_test.rb +232 -0
- data/test/action_controller/serialization_scope_name_test.rb +12 -6
- data/test/action_controller/serialization_test.rb +12 -9
- data/test/active_model_serializers/json_pointer_test.rb +15 -13
- data/test/active_model_serializers/model_test.rb +137 -4
- data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
- data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
- data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
- data/test/active_model_serializers/test/schema_test.rb +3 -2
- data/test/adapter/attributes_test.rb +40 -0
- data/test/adapter/json/collection_test.rb +14 -0
- data/test/adapter/json/has_many_test.rb +10 -2
- data/test/adapter/json/transform_test.rb +15 -15
- data/test/adapter/json_api/collection_test.rb +4 -3
- data/test/adapter/json_api/errors_test.rb +17 -19
- data/test/adapter/json_api/fields_test.rb +12 -3
- data/test/adapter/json_api/has_many_test.rb +49 -20
- data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
- data/test/adapter/json_api/json_api_test.rb +5 -7
- data/test/adapter/json_api/linked_test.rb +33 -12
- data/test/adapter/json_api/links_test.rb +4 -2
- data/test/adapter/json_api/pagination_links_test.rb +53 -13
- data/test/adapter/json_api/parse_test.rb +1 -1
- data/test/adapter/json_api/relationship_test.rb +309 -73
- data/test/adapter/json_api/resource_meta_test.rb +3 -3
- data/test/adapter/json_api/transform_test.rb +263 -253
- data/test/adapter/json_api/type_test.rb +168 -36
- data/test/adapter/json_test.rb +8 -7
- data/test/adapter/null_test.rb +1 -2
- data/test/adapter/polymorphic_test.rb +52 -5
- data/test/adapter_test.rb +1 -1
- data/test/benchmark/app.rb +1 -1
- data/test/benchmark/benchmarking_support.rb +1 -1
- data/test/benchmark/bm_active_record.rb +81 -0
- data/test/benchmark/bm_adapter.rb +38 -0
- data/test/benchmark/bm_caching.rb +16 -16
- data/test/benchmark/bm_lookup_chain.rb +83 -0
- data/test/benchmark/bm_transform.rb +21 -10
- data/test/benchmark/controllers.rb +16 -17
- data/test/benchmark/fixtures.rb +72 -72
- data/test/cache_test.rb +235 -69
- data/test/collection_serializer_test.rb +31 -14
- data/test/fixtures/active_record.rb +45 -10
- data/test/fixtures/poro.rb +124 -181
- data/test/generators/serializer_generator_test.rb +23 -5
- data/test/grape_test.rb +170 -56
- data/test/lint_test.rb +1 -1
- data/test/logger_test.rb +13 -11
- data/test/serializable_resource_test.rb +18 -22
- data/test/serializers/association_macros_test.rb +3 -2
- data/test/serializers/associations_test.rb +222 -49
- data/test/serializers/attribute_test.rb +5 -3
- data/test/serializers/attributes_test.rb +1 -1
- data/test/serializers/caching_configuration_test_isolated.rb +6 -6
- data/test/serializers/fieldset_test.rb +1 -1
- data/test/serializers/meta_test.rb +12 -6
- data/test/serializers/options_test.rb +17 -6
- data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
- data/test/serializers/reflection_test.rb +427 -0
- data/test/serializers/root_test.rb +1 -1
- data/test/serializers/serialization_test.rb +2 -2
- data/test/serializers/serializer_for_test.rb +12 -10
- data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
- data/test/support/isolated_unit.rb +9 -4
- data/test/support/rails5_shims.rb +8 -2
- data/test/support/rails_app.rb +2 -9
- data/test/support/serialization_testing.rb +31 -5
- data/test/test_helper.rb +13 -0
- metadata +130 -71
- data/.rubocop_todo.yml +0 -167
- data/docs/ARCHITECTURE.md +0 -126
- 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/active_model_serializers/key_transform_test.rb +0 -263
- data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
- data/test/adapter/json_api/relationships_test.rb +0 -199
- data/test/adapter/json_api/resource_identifier_test.rb +0 -85
- 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
|
@@ -4,6 +4,10 @@ module ActionController
|
|
|
4
4
|
module Serialization
|
|
5
5
|
class Json
|
|
6
6
|
class IncludeTest < ActionController::TestCase
|
|
7
|
+
INCLUDE_STRING = 'posts.comments'.freeze
|
|
8
|
+
INCLUDE_HASH = { posts: :comments }.freeze
|
|
9
|
+
DEEP_INCLUDE = 'posts.comments.author'.freeze
|
|
10
|
+
|
|
7
11
|
class IncludeTestController < ActionController::Base
|
|
8
12
|
def setup_data
|
|
9
13
|
ActionController::Base.cache_store.clear
|
|
@@ -38,17 +42,28 @@ module ActionController
|
|
|
38
42
|
|
|
39
43
|
def render_resource_with_include_hash
|
|
40
44
|
setup_data
|
|
41
|
-
render json: @author, include:
|
|
45
|
+
render json: @author, include: INCLUDE_HASH, adapter: :json
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
def render_resource_with_include_string
|
|
45
49
|
setup_data
|
|
46
|
-
render json: @author, include:
|
|
50
|
+
render json: @author, include: INCLUDE_STRING, adapter: :json
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
def render_resource_with_deep_include
|
|
50
54
|
setup_data
|
|
51
|
-
render json: @author, include:
|
|
55
|
+
render json: @author, include: DEEP_INCLUDE, adapter: :json
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def render_without_recursive_relationships
|
|
59
|
+
# testing recursive includes ('**') can't have any cycles in the
|
|
60
|
+
# relationships, or we enter an infinite loop.
|
|
61
|
+
author = Author.new(id: 11, name: 'Jane Doe')
|
|
62
|
+
post = Post.new(id: 12, title: 'Hello World', body: 'My first post')
|
|
63
|
+
comment = Comment.new(id: 13, body: 'Commentary')
|
|
64
|
+
author.posts = [post]
|
|
65
|
+
post.comments = [comment]
|
|
66
|
+
render json: author
|
|
52
67
|
end
|
|
53
68
|
end
|
|
54
69
|
|
|
@@ -77,34 +92,90 @@ module ActionController
|
|
|
77
92
|
def test_render_resource_with_include_hash
|
|
78
93
|
get :render_resource_with_include_hash
|
|
79
94
|
response = JSON.parse(@response.body)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
|
|
96
|
+
assert_equal(expected_include_response, response)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_render_resource_with_include_string
|
|
100
|
+
get :render_resource_with_include_string
|
|
101
|
+
|
|
102
|
+
response = JSON.parse(@response.body)
|
|
103
|
+
|
|
104
|
+
assert_equal(expected_include_response, response)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def test_render_resource_with_deep_include
|
|
108
|
+
get :render_resource_with_deep_include
|
|
109
|
+
|
|
110
|
+
response = JSON.parse(@response.body)
|
|
111
|
+
|
|
112
|
+
assert_equal(expected_deep_include_response, response)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def test_render_with_empty_default_includes
|
|
116
|
+
with_default_includes '' do
|
|
117
|
+
get :render_without_include
|
|
118
|
+
response = JSON.parse(@response.body)
|
|
119
|
+
expected = {
|
|
120
|
+
'author' => {
|
|
121
|
+
'id' => 1,
|
|
122
|
+
'name' => 'Steve K.'
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
assert_equal(expected, response)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_render_with_recursive_default_includes
|
|
130
|
+
with_default_includes '**' do
|
|
131
|
+
get :render_without_recursive_relationships
|
|
132
|
+
response = JSON.parse(@response.body)
|
|
133
|
+
|
|
134
|
+
expected = {
|
|
135
|
+
'id' => 11,
|
|
136
|
+
'name' => 'Jane Doe',
|
|
137
|
+
'roles' => nil,
|
|
138
|
+
'bio' => nil,
|
|
84
139
|
'posts' => [
|
|
85
140
|
{
|
|
86
|
-
'id' =>
|
|
141
|
+
'id' => 12,
|
|
142
|
+
'title' => 'Hello World',
|
|
143
|
+
'body' => 'My first post',
|
|
87
144
|
'comments' => [
|
|
88
145
|
{
|
|
89
|
-
'id' =>
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
'
|
|
146
|
+
'id' => 13,
|
|
147
|
+
'body' => 'Commentary',
|
|
148
|
+
'post' => nil, # not set to avoid infinite recursion
|
|
149
|
+
'author' => nil, # not set to avoid infinite recursion
|
|
93
150
|
}
|
|
94
|
-
]
|
|
151
|
+
],
|
|
152
|
+
'blog' => {
|
|
153
|
+
'id' => 999,
|
|
154
|
+
'name' => 'Custom blog',
|
|
155
|
+
'writer' => nil,
|
|
156
|
+
'articles' => nil
|
|
157
|
+
},
|
|
158
|
+
'author' => nil # not set to avoid infinite recursion
|
|
95
159
|
}
|
|
96
160
|
]
|
|
97
161
|
}
|
|
98
|
-
|
|
162
|
+
assert_equal(expected, response)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
99
165
|
|
|
100
|
-
|
|
166
|
+
def test_render_with_includes_overrides_default_includes
|
|
167
|
+
with_default_includes '' do
|
|
168
|
+
get :render_resource_with_include_hash
|
|
169
|
+
response = JSON.parse(@response.body)
|
|
170
|
+
|
|
171
|
+
assert_equal(expected_include_response, response)
|
|
172
|
+
end
|
|
101
173
|
end
|
|
102
174
|
|
|
103
|
-
|
|
104
|
-
get :render_resource_with_include_string
|
|
175
|
+
private
|
|
105
176
|
|
|
106
|
-
|
|
107
|
-
|
|
177
|
+
def expected_include_response
|
|
178
|
+
{
|
|
108
179
|
'author' => {
|
|
109
180
|
'id' => 1,
|
|
110
181
|
'name' => 'Steve K.',
|
|
@@ -123,15 +194,10 @@ module ActionController
|
|
|
123
194
|
]
|
|
124
195
|
}
|
|
125
196
|
}
|
|
126
|
-
|
|
127
|
-
assert_equal(expected, response)
|
|
128
197
|
end
|
|
129
198
|
|
|
130
|
-
def
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
response = JSON.parse(@response.body)
|
|
134
|
-
expected = {
|
|
199
|
+
def expected_deep_include_response
|
|
200
|
+
{
|
|
135
201
|
'author' => {
|
|
136
202
|
'id' => 1,
|
|
137
203
|
'name' => 'Steve K.',
|
|
@@ -158,8 +224,21 @@ module ActionController
|
|
|
158
224
|
]
|
|
159
225
|
}
|
|
160
226
|
}
|
|
227
|
+
end
|
|
161
228
|
|
|
162
|
-
|
|
229
|
+
def with_default_includes(include_directive)
|
|
230
|
+
original = ActiveModelSerializers.config.default_includes
|
|
231
|
+
ActiveModelSerializers.config.default_includes = include_directive
|
|
232
|
+
clear_include_directive_cache
|
|
233
|
+
yield
|
|
234
|
+
ensure
|
|
235
|
+
ActiveModelSerializers.config.default_includes = original
|
|
236
|
+
clear_include_directive_cache
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def clear_include_directive_cache
|
|
240
|
+
ActiveModelSerializers
|
|
241
|
+
.instance_variable_set(:@default_include_directive, nil)
|
|
163
242
|
end
|
|
164
243
|
end
|
|
165
244
|
end
|
|
@@ -45,7 +45,7 @@ module ActionController
|
|
|
45
45
|
response = JSON.parse(@response.body)
|
|
46
46
|
expected = {
|
|
47
47
|
'restriction_for_id' => '67',
|
|
48
|
-
'restriction_for_type' => '
|
|
48
|
+
'restriction_for_type' => 'Discount',
|
|
49
49
|
'restricted_to_id' => nil,
|
|
50
50
|
'restricted_to_type' => nil
|
|
51
51
|
}
|
|
@@ -7,18 +7,17 @@ module ActionController
|
|
|
7
7
|
def test_active_model_with_multiple_errors
|
|
8
8
|
get :render_resource_with_errors
|
|
9
9
|
|
|
10
|
-
expected_errors_object =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
]
|
|
10
|
+
expected_errors_object = {
|
|
11
|
+
errors: [
|
|
12
|
+
{ source: { pointer: '/data/attributes/name' }, detail: 'cannot be nil' },
|
|
13
|
+
{ source: { pointer: '/data/attributes/name' }, detail: 'must be longer' },
|
|
14
|
+
{ source: { pointer: '/data/attributes/id' }, detail: 'must be a uuid' }
|
|
15
|
+
]
|
|
17
16
|
}.to_json
|
|
18
|
-
assert_equal
|
|
17
|
+
assert_equal json_response_body.to_json, expected_errors_object
|
|
19
18
|
end
|
|
20
19
|
|
|
21
|
-
def
|
|
20
|
+
def json_response_body
|
|
22
21
|
JSON.load(@response.body)
|
|
23
22
|
end
|
|
24
23
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class JsonApi
|
|
6
|
+
class FieldsTest < ActionController::TestCase
|
|
7
|
+
class FieldsTestController < ActionController::Base
|
|
8
|
+
class AuthorWithName < Author
|
|
9
|
+
attributes :first_name, :last_name
|
|
10
|
+
end
|
|
11
|
+
class AuthorWithNameSerializer < AuthorSerializer
|
|
12
|
+
type 'authors'
|
|
13
|
+
end
|
|
14
|
+
class PostWithPublishAt < Post
|
|
15
|
+
attributes :publish_at
|
|
16
|
+
end
|
|
17
|
+
class PostWithPublishAtSerializer < ActiveModel::Serializer
|
|
18
|
+
type 'posts'
|
|
19
|
+
attributes :title, :body, :publish_at
|
|
20
|
+
belongs_to :author
|
|
21
|
+
has_many :comments
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def setup_post
|
|
25
|
+
ActionController::Base.cache_store.clear
|
|
26
|
+
@author = AuthorWithName.new(id: 1, first_name: 'Bob', last_name: 'Jones')
|
|
27
|
+
@comment1 = Comment.new(id: 7, body: 'cool', author: @author)
|
|
28
|
+
@comment2 = Comment.new(id: 12, body: 'awesome', author: @author)
|
|
29
|
+
@post = PostWithPublishAt.new(id: 1337, title: 'Title 1', body: 'Body 1',
|
|
30
|
+
author: @author, comments: [@comment1, @comment2],
|
|
31
|
+
publish_at: '2020-03-16T03:55:25.291Z')
|
|
32
|
+
@comment1.post = @post
|
|
33
|
+
@comment2.post = @post
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def render_fields_works_on_relationships
|
|
37
|
+
setup_post
|
|
38
|
+
render json: @post, serializer: PostWithPublishAtSerializer, adapter: :json_api, fields: { posts: [:author] }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
tests FieldsTestController
|
|
43
|
+
|
|
44
|
+
test 'fields works on relationships' do
|
|
45
|
+
get :render_fields_works_on_relationships
|
|
46
|
+
response = JSON.parse(@response.body)
|
|
47
|
+
expected = {
|
|
48
|
+
'data' => {
|
|
49
|
+
'id' => '1337',
|
|
50
|
+
'type' => 'posts',
|
|
51
|
+
'relationships' => {
|
|
52
|
+
'author' => {
|
|
53
|
+
'data' => {
|
|
54
|
+
'id' => '1',
|
|
55
|
+
'type' => 'authors'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
assert_equal expected, response
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -3,9 +3,8 @@ require 'test_helper'
|
|
|
3
3
|
module ActionController
|
|
4
4
|
module Serialization
|
|
5
5
|
class JsonApi
|
|
6
|
-
class LinkedTest <
|
|
6
|
+
class LinkedTest < ActionDispatch::IntegrationTest
|
|
7
7
|
class LinkedTestController < ActionController::Base
|
|
8
|
-
require 'active_model_serializers/register_jsonapi_renderer'
|
|
9
8
|
def setup_post
|
|
10
9
|
ActionController::Base.cache_store.clear
|
|
11
10
|
@role1 = Role.new(id: 1, name: 'admin')
|
|
@@ -39,62 +38,68 @@ module ActionController
|
|
|
39
38
|
|
|
40
39
|
def render_resource_without_include
|
|
41
40
|
setup_post
|
|
42
|
-
render
|
|
41
|
+
render json: @post
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
def render_resource_with_include
|
|
46
45
|
setup_post
|
|
47
|
-
render
|
|
46
|
+
render json: @post, adapter: :json_api, include: [:author]
|
|
48
47
|
end
|
|
49
48
|
|
|
50
49
|
def render_resource_with_include_of_custom_key_by_original
|
|
51
50
|
setup_post
|
|
52
|
-
render
|
|
51
|
+
render json: @post, adapter: :json_api, include: [:reviews], serializer: PostWithCustomKeysSerializer
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
def render_resource_with_nested_include
|
|
56
55
|
setup_post
|
|
57
|
-
render
|
|
56
|
+
render json: @post, adapter: :json_api, include: [comments: [:author]]
|
|
58
57
|
end
|
|
59
58
|
|
|
60
59
|
def render_resource_with_nested_has_many_include_wildcard
|
|
61
60
|
setup_post
|
|
62
|
-
render
|
|
61
|
+
render json: @post, adapter: :json_api, include: 'author.*'
|
|
63
62
|
end
|
|
64
63
|
|
|
65
64
|
def render_resource_with_missing_nested_has_many_include
|
|
66
65
|
setup_post
|
|
67
66
|
@post.author = @author2 # author2 has no roles.
|
|
68
|
-
render
|
|
67
|
+
render json: @post, adapter: :json_api, include: [author: [:roles]]
|
|
69
68
|
end
|
|
70
69
|
|
|
71
70
|
def render_collection_with_missing_nested_has_many_include
|
|
72
71
|
setup_post
|
|
73
72
|
@post.author = @author2
|
|
74
|
-
render
|
|
73
|
+
render json: [@post, @post2], adapter: :json_api, include: [author: [:roles]]
|
|
75
74
|
end
|
|
76
75
|
|
|
77
76
|
def render_collection_without_include
|
|
78
77
|
setup_post
|
|
79
|
-
render
|
|
78
|
+
render json: [@post], adapter: :json_api
|
|
80
79
|
end
|
|
81
80
|
|
|
82
81
|
def render_collection_with_include
|
|
83
82
|
setup_post
|
|
84
|
-
render
|
|
83
|
+
render json: [@post], adapter: :json_api, include: 'author, comments'
|
|
85
84
|
end
|
|
86
85
|
end
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
setup do
|
|
88
|
+
@routes = Rails.application.routes.draw do
|
|
89
|
+
ActiveSupport::Deprecation.silence do
|
|
90
|
+
match ':action', to: LinkedTestController, via: [:get, :post]
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
89
94
|
|
|
90
95
|
def test_render_resource_without_include
|
|
91
|
-
get
|
|
96
|
+
get '/render_resource_without_include'
|
|
92
97
|
response = JSON.parse(@response.body)
|
|
93
98
|
refute response.key? 'included'
|
|
94
99
|
end
|
|
95
100
|
|
|
96
101
|
def test_render_resource_with_include
|
|
97
|
-
get
|
|
102
|
+
get '/render_resource_with_include'
|
|
98
103
|
response = JSON.parse(@response.body)
|
|
99
104
|
assert response.key? 'included'
|
|
100
105
|
assert_equal 1, response['included'].size
|
|
@@ -102,7 +107,7 @@ module ActionController
|
|
|
102
107
|
end
|
|
103
108
|
|
|
104
109
|
def test_render_resource_with_nested_has_many_include
|
|
105
|
-
get
|
|
110
|
+
get '/render_resource_with_nested_has_many_include_wildcard'
|
|
106
111
|
response = JSON.parse(@response.body)
|
|
107
112
|
expected_linked = [
|
|
108
113
|
{
|
|
@@ -144,7 +149,7 @@ module ActionController
|
|
|
144
149
|
end
|
|
145
150
|
|
|
146
151
|
def test_render_resource_with_include_of_custom_key_by_original
|
|
147
|
-
get
|
|
152
|
+
get '/render_resource_with_include_of_custom_key_by_original'
|
|
148
153
|
response = JSON.parse(@response.body)
|
|
149
154
|
assert response.key? 'included'
|
|
150
155
|
|
|
@@ -156,39 +161,39 @@ module ActionController
|
|
|
156
161
|
end
|
|
157
162
|
|
|
158
163
|
def test_render_resource_with_nested_include
|
|
159
|
-
get
|
|
164
|
+
get '/render_resource_with_nested_include'
|
|
160
165
|
response = JSON.parse(@response.body)
|
|
161
166
|
assert response.key? 'included'
|
|
162
167
|
assert_equal 3, response['included'].size
|
|
163
168
|
end
|
|
164
169
|
|
|
165
170
|
def test_render_collection_without_include
|
|
166
|
-
get
|
|
171
|
+
get '/render_collection_without_include'
|
|
167
172
|
response = JSON.parse(@response.body)
|
|
168
173
|
refute response.key? 'included'
|
|
169
174
|
end
|
|
170
175
|
|
|
171
176
|
def test_render_collection_with_include
|
|
172
|
-
get
|
|
177
|
+
get '/render_collection_with_include'
|
|
173
178
|
response = JSON.parse(@response.body)
|
|
174
179
|
assert response.key? 'included'
|
|
175
180
|
end
|
|
176
181
|
|
|
177
182
|
def test_render_resource_with_nested_attributes_even_when_missing_associations
|
|
178
|
-
get
|
|
183
|
+
get '/render_resource_with_missing_nested_has_many_include'
|
|
179
184
|
response = JSON.parse(@response.body)
|
|
180
185
|
assert response.key? 'included'
|
|
181
|
-
refute
|
|
186
|
+
refute include_type?(response['included'], 'roles')
|
|
182
187
|
end
|
|
183
188
|
|
|
184
189
|
def test_render_collection_with_missing_nested_has_many_include
|
|
185
|
-
get
|
|
190
|
+
get '/render_collection_with_missing_nested_has_many_include'
|
|
186
191
|
response = JSON.parse(@response.body)
|
|
187
192
|
assert response.key? 'included'
|
|
188
|
-
assert
|
|
193
|
+
assert include_type?(response['included'], 'roles')
|
|
189
194
|
end
|
|
190
195
|
|
|
191
|
-
def
|
|
196
|
+
def include_type?(collection, value)
|
|
192
197
|
collection.detect { |i| i['type'] == value }
|
|
193
198
|
end
|
|
194
199
|
end
|
|
@@ -14,9 +14,9 @@ module ActionController
|
|
|
14
14
|
class PaginationTestController < ActionController::Base
|
|
15
15
|
def setup
|
|
16
16
|
@array = [
|
|
17
|
-
Profile.new(
|
|
18
|
-
Profile.new(
|
|
19
|
-
Profile.new(
|
|
17
|
+
Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
|
|
18
|
+
Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
|
|
19
|
+
Profile.new(name: 'Name 3', description: 'Description 3', comments: 'Comments 3')
|
|
20
20
|
]
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -48,20 +48,22 @@ module ActionController
|
|
|
48
48
|
|
|
49
49
|
def test_render_pagination_links_with_will_paginate
|
|
50
50
|
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
|
|
52
|
+
'prev' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
|
|
53
|
+
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
|
|
54
|
+
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
|
|
55
55
|
|
|
56
56
|
get :render_pagination_using_will_paginate, params: { page: { number: 2, size: 1 } }
|
|
57
57
|
response = JSON.parse(@response.body)
|
|
58
58
|
assert_equal expected_links, response['links']
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
def
|
|
61
|
+
def test_render_only_first_last_and_next_pagination_links
|
|
62
62
|
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
|
|
64
|
+
'prev' => nil,
|
|
65
|
+
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
|
|
66
|
+
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2" }
|
|
65
67
|
get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 } }
|
|
66
68
|
response = JSON.parse(@response.body)
|
|
67
69
|
assert_equal expected_links, response['links']
|
|
@@ -69,37 +71,43 @@ module ActionController
|
|
|
69
71
|
|
|
70
72
|
def test_render_pagination_links_with_kaminari
|
|
71
73
|
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
|
|
75
|
+
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
|
|
76
|
+
'next' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
|
|
77
|
+
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
|
|
76
78
|
get :render_pagination_using_kaminari, params: { page: { number: 2, size: 1 } }
|
|
77
79
|
response = JSON.parse(@response.body)
|
|
78
80
|
assert_equal expected_links, response['links']
|
|
79
81
|
end
|
|
80
82
|
|
|
81
|
-
def
|
|
83
|
+
def test_render_only_prev_first_and_last_pagination_links
|
|
82
84
|
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
|
|
86
|
+
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
|
|
87
|
+
'next' => nil,
|
|
88
|
+
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
|
|
85
89
|
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
|
|
86
90
|
response = JSON.parse(@response.body)
|
|
87
91
|
assert_equal expected_links, response['links']
|
|
88
92
|
end
|
|
89
93
|
|
|
90
|
-
def
|
|
94
|
+
def test_render_only_first_last_and_next_pagination_links_with_additional_params
|
|
91
95
|
expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
|
|
97
|
+
'prev' => nil,
|
|
98
|
+
'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
|
|
99
|
+
'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional" }
|
|
94
100
|
get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
|
|
95
101
|
response = JSON.parse(@response.body)
|
|
96
102
|
assert_equal expected_links, response['links']
|
|
97
103
|
end
|
|
98
104
|
|
|
99
|
-
def
|
|
105
|
+
def test_render_only_prev_first_and_last_pagination_links_with_additional_params
|
|
100
106
|
expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional",
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
|
|
108
|
+
'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional",
|
|
109
|
+
'next' => nil,
|
|
110
|
+
'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional" }
|
|
103
111
|
get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
|
|
104
112
|
response = JSON.parse(@response.body)
|
|
105
113
|
assert_equal expected_links, response['links']
|
|
@@ -5,7 +5,17 @@ module ActionController
|
|
|
5
5
|
class JsonApi
|
|
6
6
|
class KeyTransformTest < ActionController::TestCase
|
|
7
7
|
class KeyTransformTestController < ActionController::Base
|
|
8
|
-
Post
|
|
8
|
+
class Post < ::Model
|
|
9
|
+
attributes :title, :body, :publish_at
|
|
10
|
+
associations :author, :top_comments
|
|
11
|
+
end
|
|
12
|
+
class Author < ::Model
|
|
13
|
+
attributes :first_name, :last_name
|
|
14
|
+
end
|
|
15
|
+
class TopComment < ::Model
|
|
16
|
+
attributes :body
|
|
17
|
+
associations :author, :post
|
|
18
|
+
end
|
|
9
19
|
class PostSerializer < ActiveModel::Serializer
|
|
10
20
|
type 'posts'
|
|
11
21
|
attributes :title, :body, :publish_at
|
|
@@ -22,13 +32,11 @@ module ActionController
|
|
|
22
32
|
end
|
|
23
33
|
end
|
|
24
34
|
|
|
25
|
-
Author = Class.new(::Model)
|
|
26
35
|
class AuthorSerializer < ActiveModel::Serializer
|
|
27
36
|
type 'authors'
|
|
28
37
|
attributes :first_name, :last_name
|
|
29
38
|
end
|
|
30
39
|
|
|
31
|
-
TopComment = Class.new(::Model)
|
|
32
40
|
class TopCommentSerializer < ActiveModel::Serializer
|
|
33
41
|
type 'top_comments'
|
|
34
42
|
attributes :body
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
module ActionController
|
|
4
|
+
module Serialization
|
|
5
|
+
class LookupProcTest < ActionController::TestCase
|
|
6
|
+
module Api
|
|
7
|
+
module V3
|
|
8
|
+
class PostCustomSerializer < ActiveModel::Serializer
|
|
9
|
+
attributes :title, :body
|
|
10
|
+
|
|
11
|
+
belongs_to :author
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class AuthorCustomSerializer < ActiveModel::Serializer
|
|
15
|
+
attributes :name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class LookupProcTestController < ActionController::Base
|
|
19
|
+
def implicit_namespaced_serializer
|
|
20
|
+
author = Author.new(name: 'Bob')
|
|
21
|
+
post = Post.new(title: 'New Post', body: 'Body', author: author)
|
|
22
|
+
|
|
23
|
+
render json: post
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
tests Api::V3::LookupProcTestController
|
|
30
|
+
|
|
31
|
+
test 'implicitly uses namespaced serializer' do
|
|
32
|
+
controller_namespace = lambda do |resource_class, _parent_serializer_class, namespace|
|
|
33
|
+
"#{namespace}::#{resource_class}CustomSerializer" if namespace
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
with_prepended_lookup(controller_namespace) do
|
|
37
|
+
get :implicit_namespaced_serializer
|
|
38
|
+
|
|
39
|
+
assert_serializer Api::V3::PostCustomSerializer
|
|
40
|
+
|
|
41
|
+
expected = { 'title' => 'New Post', 'body' => 'Body', 'author' => { 'name' => 'Bob' } }
|
|
42
|
+
actual = JSON.parse(@response.body)
|
|
43
|
+
|
|
44
|
+
assert_equal expected, actual
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|