agi_active_model_serializers 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.
Files changed (220) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +35 -0
  5. data/.rubocop.yml +102 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +51 -0
  8. data/CHANGELOG.md +612 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +56 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +307 -0
  14. data/Rakefile +103 -0
  15. data/active_model_serializers.gemspec +63 -0
  16. data/appveyor.yml +24 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/serve_benchmark +39 -0
  20. data/docs/README.md +41 -0
  21. data/docs/STYLE.md +58 -0
  22. data/docs/general/adapters.md +247 -0
  23. data/docs/general/caching.md +58 -0
  24. data/docs/general/configuration_options.md +169 -0
  25. data/docs/general/deserialization.md +100 -0
  26. data/docs/general/fields.md +31 -0
  27. data/docs/general/getting_started.md +133 -0
  28. data/docs/general/instrumentation.md +40 -0
  29. data/docs/general/key_transforms.md +40 -0
  30. data/docs/general/logging.md +14 -0
  31. data/docs/general/rendering.md +279 -0
  32. data/docs/general/serializers.md +461 -0
  33. data/docs/how-open-source-maintained.jpg +0 -0
  34. data/docs/howto/add_pagination_links.md +138 -0
  35. data/docs/howto/add_relationship_links.md +137 -0
  36. data/docs/howto/add_root_key.md +55 -0
  37. data/docs/howto/grape_integration.md +42 -0
  38. data/docs/howto/outside_controller_use.md +65 -0
  39. data/docs/howto/passing_arbitrary_options.md +27 -0
  40. data/docs/howto/serialize_poro.md +32 -0
  41. data/docs/howto/test.md +154 -0
  42. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  43. data/docs/integrations/ember-and-json-api.md +144 -0
  44. data/docs/integrations/grape.md +19 -0
  45. data/docs/jsonapi/errors.md +56 -0
  46. data/docs/jsonapi/schema.md +151 -0
  47. data/docs/jsonapi/schema/schema.json +366 -0
  48. data/docs/rfcs/0000-namespace.md +106 -0
  49. data/docs/rfcs/template.md +15 -0
  50. data/lib/action_controller/serialization.rb +66 -0
  51. data/lib/active_model/serializable_resource.rb +11 -0
  52. data/lib/active_model/serializer.rb +231 -0
  53. data/lib/active_model/serializer/adapter.rb +24 -0
  54. data/lib/active_model/serializer/adapter/attributes.rb +15 -0
  55. data/lib/active_model/serializer/adapter/base.rb +18 -0
  56. data/lib/active_model/serializer/adapter/json.rb +15 -0
  57. data/lib/active_model/serializer/adapter/json_api.rb +15 -0
  58. data/lib/active_model/serializer/adapter/null.rb +15 -0
  59. data/lib/active_model/serializer/array_serializer.rb +12 -0
  60. data/lib/active_model/serializer/association.rb +34 -0
  61. data/lib/active_model/serializer/attribute.rb +25 -0
  62. data/lib/active_model/serializer/belongs_to_reflection.rb +7 -0
  63. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +87 -0
  65. data/lib/active_model/serializer/concerns/associations.rb +102 -0
  66. data/lib/active_model/serializer/concerns/attributes.rb +82 -0
  67. data/lib/active_model/serializer/concerns/caching.rb +292 -0
  68. data/lib/active_model/serializer/concerns/configuration.rb +59 -0
  69. data/lib/active_model/serializer/concerns/links.rb +35 -0
  70. data/lib/active_model/serializer/concerns/meta.rb +29 -0
  71. data/lib/active_model/serializer/concerns/type.rb +25 -0
  72. data/lib/active_model/serializer/error_serializer.rb +14 -0
  73. data/lib/active_model/serializer/errors_serializer.rb +32 -0
  74. data/lib/active_model/serializer/field.rb +90 -0
  75. data/lib/active_model/serializer/fieldset.rb +31 -0
  76. data/lib/active_model/serializer/has_many_reflection.rb +7 -0
  77. data/lib/active_model/serializer/has_one_reflection.rb +7 -0
  78. data/lib/active_model/serializer/lint.rb +150 -0
  79. data/lib/active_model/serializer/null.rb +17 -0
  80. data/lib/active_model/serializer/reflection.rb +163 -0
  81. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  82. data/lib/active_model/serializer/version.rb +5 -0
  83. data/lib/active_model_serializers.rb +53 -0
  84. data/lib/active_model_serializers/adapter.rb +98 -0
  85. data/lib/active_model_serializers/adapter/attributes.rb +13 -0
  86. data/lib/active_model_serializers/adapter/base.rb +83 -0
  87. data/lib/active_model_serializers/adapter/json.rb +21 -0
  88. data/lib/active_model_serializers/adapter/json_api.rb +517 -0
  89. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +213 -0
  90. data/lib/active_model_serializers/adapter/json_api/error.rb +96 -0
  91. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +49 -0
  92. data/lib/active_model_serializers/adapter/json_api/link.rb +83 -0
  93. data/lib/active_model_serializers/adapter/json_api/meta.rb +37 -0
  94. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +69 -0
  95. data/lib/active_model_serializers/adapter/json_api/relationship.rb +63 -0
  96. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +51 -0
  97. data/lib/active_model_serializers/adapter/null.rb +9 -0
  98. data/lib/active_model_serializers/callbacks.rb +55 -0
  99. data/lib/active_model_serializers/deprecate.rb +54 -0
  100. data/lib/active_model_serializers/deserialization.rb +15 -0
  101. data/lib/active_model_serializers/json_pointer.rb +14 -0
  102. data/lib/active_model_serializers/logging.rb +122 -0
  103. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  104. data/lib/active_model_serializers/model.rb +71 -0
  105. data/lib/active_model_serializers/railtie.rb +48 -0
  106. data/lib/active_model_serializers/register_jsonapi_renderer.rb +78 -0
  107. data/lib/active_model_serializers/serializable_resource.rb +82 -0
  108. data/lib/active_model_serializers/serialization_context.rb +39 -0
  109. data/lib/active_model_serializers/test.rb +7 -0
  110. data/lib/active_model_serializers/test/schema.rb +138 -0
  111. data/lib/active_model_serializers/test/serializer.rb +125 -0
  112. data/lib/generators/rails/USAGE +6 -0
  113. data/lib/generators/rails/resource_override.rb +10 -0
  114. data/lib/generators/rails/serializer_generator.rb +36 -0
  115. data/lib/generators/rails/templates/serializer.rb.erb +15 -0
  116. data/lib/grape/active_model_serializers.rb +16 -0
  117. data/lib/grape/formatters/active_model_serializers.rb +32 -0
  118. data/lib/grape/helpers/active_model_serializers.rb +17 -0
  119. data/test/action_controller/adapter_selector_test.rb +53 -0
  120. data/test/action_controller/explicit_serializer_test.rb +135 -0
  121. data/test/action_controller/json/include_test.rb +246 -0
  122. data/test/action_controller/json_api/deserialization_test.rb +112 -0
  123. data/test/action_controller/json_api/errors_test.rb +40 -0
  124. data/test/action_controller/json_api/fields_test.rb +66 -0
  125. data/test/action_controller/json_api/linked_test.rb +202 -0
  126. data/test/action_controller/json_api/pagination_test.rb +116 -0
  127. data/test/action_controller/json_api/transform_test.rb +189 -0
  128. data/test/action_controller/lookup_proc_test.rb +49 -0
  129. data/test/action_controller/namespace_lookup_test.rb +232 -0
  130. data/test/action_controller/serialization_scope_name_test.rb +229 -0
  131. data/test/action_controller/serialization_test.rb +472 -0
  132. data/test/active_model_serializers/adapter_for_test.rb +208 -0
  133. data/test/active_model_serializers/json_pointer_test.rb +22 -0
  134. data/test/active_model_serializers/logging_test.rb +77 -0
  135. data/test/active_model_serializers/model_test.rb +69 -0
  136. data/test/active_model_serializers/railtie_test_isolated.rb +63 -0
  137. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  138. data/test/active_model_serializers/serialization_context_test_isolated.rb +71 -0
  139. data/test/active_model_serializers/test/schema_test.rb +131 -0
  140. data/test/active_model_serializers/test/serializer_test.rb +62 -0
  141. data/test/active_record_test.rb +9 -0
  142. data/test/adapter/attributes_test.rb +43 -0
  143. data/test/adapter/deprecation_test.rb +100 -0
  144. data/test/adapter/json/belongs_to_test.rb +45 -0
  145. data/test/adapter/json/collection_test.rb +104 -0
  146. data/test/adapter/json/has_many_test.rb +45 -0
  147. data/test/adapter/json/transform_test.rb +93 -0
  148. data/test/adapter/json_api/belongs_to_test.rb +155 -0
  149. data/test/adapter/json_api/collection_test.rb +96 -0
  150. data/test/adapter/json_api/errors_test.rb +76 -0
  151. data/test/adapter/json_api/fields_test.rb +96 -0
  152. data/test/adapter/json_api/has_many_embed_ids_test.rb +43 -0
  153. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +96 -0
  154. data/test/adapter/json_api/has_many_test.rb +165 -0
  155. data/test/adapter/json_api/has_one_test.rb +80 -0
  156. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +168 -0
  157. data/test/adapter/json_api/json_api_test.rb +33 -0
  158. data/test/adapter/json_api/linked_test.rb +413 -0
  159. data/test/adapter/json_api/links_test.rb +95 -0
  160. data/test/adapter/json_api/pagination_links_test.rb +193 -0
  161. data/test/adapter/json_api/parse_test.rb +137 -0
  162. data/test/adapter/json_api/relationship_test.rb +397 -0
  163. data/test/adapter/json_api/resource_identifier_test.rb +110 -0
  164. data/test/adapter/json_api/resource_meta_test.rb +100 -0
  165. data/test/adapter/json_api/toplevel_jsonapi_test.rb +82 -0
  166. data/test/adapter/json_api/transform_test.rb +512 -0
  167. data/test/adapter/json_api/type_test.rb +61 -0
  168. data/test/adapter/json_test.rb +46 -0
  169. data/test/adapter/null_test.rb +22 -0
  170. data/test/adapter/polymorphic_test.rb +171 -0
  171. data/test/adapter_test.rb +67 -0
  172. data/test/array_serializer_test.rb +22 -0
  173. data/test/benchmark/app.rb +65 -0
  174. data/test/benchmark/benchmarking_support.rb +67 -0
  175. data/test/benchmark/bm_active_record.rb +81 -0
  176. data/test/benchmark/bm_adapter.rb +38 -0
  177. data/test/benchmark/bm_caching.rb +119 -0
  178. data/test/benchmark/bm_lookup_chain.rb +83 -0
  179. data/test/benchmark/bm_transform.rb +45 -0
  180. data/test/benchmark/config.ru +3 -0
  181. data/test/benchmark/controllers.rb +83 -0
  182. data/test/benchmark/fixtures.rb +219 -0
  183. data/test/cache_test.rb +595 -0
  184. data/test/collection_serializer_test.rb +123 -0
  185. data/test/fixtures/active_record.rb +113 -0
  186. data/test/fixtures/poro.rb +232 -0
  187. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  188. data/test/generators/serializer_generator_test.rb +74 -0
  189. data/test/grape_test.rb +178 -0
  190. data/test/lint_test.rb +49 -0
  191. data/test/logger_test.rb +20 -0
  192. data/test/poro_test.rb +9 -0
  193. data/test/serializable_resource_test.rb +79 -0
  194. data/test/serializers/association_macros_test.rb +37 -0
  195. data/test/serializers/associations_test.rb +383 -0
  196. data/test/serializers/attribute_test.rb +153 -0
  197. data/test/serializers/attributes_test.rb +52 -0
  198. data/test/serializers/caching_configuration_test_isolated.rb +170 -0
  199. data/test/serializers/configuration_test.rb +32 -0
  200. data/test/serializers/fieldset_test.rb +14 -0
  201. data/test/serializers/meta_test.rb +202 -0
  202. data/test/serializers/options_test.rb +32 -0
  203. data/test/serializers/read_attribute_for_serialization_test.rb +79 -0
  204. data/test/serializers/root_test.rb +21 -0
  205. data/test/serializers/serialization_test.rb +55 -0
  206. data/test/serializers/serializer_for_test.rb +136 -0
  207. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  208. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  209. data/test/support/isolated_unit.rb +82 -0
  210. data/test/support/rails5_shims.rb +53 -0
  211. data/test/support/rails_app.rb +36 -0
  212. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  213. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  214. data/test/support/schemas/custom/show.json +7 -0
  215. data/test/support/schemas/hyper_schema.json +93 -0
  216. data/test/support/schemas/render_using_json_api.json +43 -0
  217. data/test/support/schemas/simple_json_pointers.json +10 -0
  218. data/test/support/serialization_testing.rb +71 -0
  219. data/test/test_helper.rb +58 -0
  220. metadata +602 -0
@@ -0,0 +1,202 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class JsonApi
6
+ class LinkedTest < ActionDispatch::IntegrationTest
7
+ class LinkedTestController < ActionController::Base
8
+ def setup_post
9
+ ActionController::Base.cache_store.clear
10
+ @role1 = Role.new(id: 1, name: 'admin')
11
+ @role2 = Role.new(id: 2, name: 'colab')
12
+ @author = Author.new(id: 1, name: 'Steve K.')
13
+ @author.posts = []
14
+ @author.bio = nil
15
+ @author.roles = [@role1, @role2]
16
+ @role1.author = @author
17
+ @role2.author = @author
18
+ @author2 = Author.new(id: 2, name: 'Anonymous')
19
+ @author2.posts = []
20
+ @author2.bio = nil
21
+ @author2.roles = []
22
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body')
23
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
24
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
25
+ @post.comments = [@first_comment, @second_comment]
26
+ @post.author = @author
27
+ @first_comment.post = @post
28
+ @first_comment.author = @author2
29
+ @second_comment.post = @post
30
+ @second_comment.author = nil
31
+ @post2 = Post.new(id: 2, title: 'Another Post', body: 'Body')
32
+ @post2.author = @author
33
+ @post2.comments = []
34
+ @blog = Blog.new(id: 1, name: 'My Blog!!')
35
+ @post.blog = @blog
36
+ @post2.blog = @blog
37
+ end
38
+
39
+ def render_resource_without_include
40
+ setup_post
41
+ render json: @post
42
+ end
43
+
44
+ def render_resource_with_include
45
+ setup_post
46
+ render json: @post, adapter: :json_api, include: [:author]
47
+ end
48
+
49
+ def render_resource_with_include_of_custom_key_by_original
50
+ setup_post
51
+ render json: @post, adapter: :json_api, include: [:reviews], serializer: PostWithCustomKeysSerializer
52
+ end
53
+
54
+ def render_resource_with_nested_include
55
+ setup_post
56
+ render json: @post, adapter: :json_api, include: [comments: [:author]]
57
+ end
58
+
59
+ def render_resource_with_nested_has_many_include_wildcard
60
+ setup_post
61
+ render json: @post, adapter: :json_api, include: 'author.*'
62
+ end
63
+
64
+ def render_resource_with_missing_nested_has_many_include
65
+ setup_post
66
+ @post.author = @author2 # author2 has no roles.
67
+ render json: @post, adapter: :json_api, include: [author: [:roles]]
68
+ end
69
+
70
+ def render_collection_with_missing_nested_has_many_include
71
+ setup_post
72
+ @post.author = @author2
73
+ render json: [@post, @post2], adapter: :json_api, include: [author: [:roles]]
74
+ end
75
+
76
+ def render_collection_without_include
77
+ setup_post
78
+ render json: [@post], adapter: :json_api
79
+ end
80
+
81
+ def render_collection_with_include
82
+ setup_post
83
+ render json: [@post], adapter: :json_api, include: 'author, comments'
84
+ end
85
+ end
86
+
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
94
+
95
+ def test_render_resource_without_include
96
+ get '/render_resource_without_include'
97
+ response = JSON.parse(@response.body)
98
+ refute response.key? 'included'
99
+ end
100
+
101
+ def test_render_resource_with_include
102
+ get '/render_resource_with_include'
103
+ response = JSON.parse(@response.body)
104
+ assert response.key? 'included'
105
+ assert_equal 1, response['included'].size
106
+ assert_equal 'Steve K.', response['included'].first['attributes']['name']
107
+ end
108
+
109
+ def test_render_resource_with_nested_has_many_include
110
+ get '/render_resource_with_nested_has_many_include_wildcard'
111
+ response = JSON.parse(@response.body)
112
+ expected_linked = [
113
+ {
114
+ 'id' => '1',
115
+ 'type' => 'authors',
116
+ 'attributes' => {
117
+ 'name' => 'Steve K.'
118
+ },
119
+ 'relationships' => {
120
+ 'posts' => { 'data' => [] },
121
+ 'roles' => { 'data' => [{ 'type' => 'roles', 'id' => '1' }, { 'type' => 'roles', 'id' => '2' }] },
122
+ 'bio' => { 'data' => nil }
123
+ }
124
+ }, {
125
+ 'id' => '1',
126
+ 'type' => 'roles',
127
+ 'attributes' => {
128
+ 'name' => 'admin',
129
+ 'description' => nil,
130
+ 'slug' => 'admin-1'
131
+ },
132
+ 'relationships' => {
133
+ 'author' => { 'data' => { 'type' => 'authors', 'id' => '1' } }
134
+ }
135
+ }, {
136
+ 'id' => '2',
137
+ 'type' => 'roles',
138
+ 'attributes' => {
139
+ 'name' => 'colab',
140
+ 'description' => nil,
141
+ 'slug' => 'colab-2'
142
+ },
143
+ 'relationships' => {
144
+ 'author' => { 'data' => { 'type' => 'authors', 'id' => '1' } }
145
+ }
146
+ }
147
+ ]
148
+ assert_equal expected_linked, response['included']
149
+ end
150
+
151
+ def test_render_resource_with_include_of_custom_key_by_original
152
+ get '/render_resource_with_include_of_custom_key_by_original'
153
+ response = JSON.parse(@response.body)
154
+ assert response.key? 'included'
155
+
156
+ relationships = response['data']['relationships']
157
+
158
+ assert_includes relationships, 'reviews'
159
+ assert_includes relationships, 'writer'
160
+ assert_includes relationships, 'site'
161
+ end
162
+
163
+ def test_render_resource_with_nested_include
164
+ get '/render_resource_with_nested_include'
165
+ response = JSON.parse(@response.body)
166
+ assert response.key? 'included'
167
+ assert_equal 3, response['included'].size
168
+ end
169
+
170
+ def test_render_collection_without_include
171
+ get '/render_collection_without_include'
172
+ response = JSON.parse(@response.body)
173
+ refute response.key? 'included'
174
+ end
175
+
176
+ def test_render_collection_with_include
177
+ get '/render_collection_with_include'
178
+ response = JSON.parse(@response.body)
179
+ assert response.key? 'included'
180
+ end
181
+
182
+ def test_render_resource_with_nested_attributes_even_when_missing_associations
183
+ get '/render_resource_with_missing_nested_has_many_include'
184
+ response = JSON.parse(@response.body)
185
+ assert response.key? 'included'
186
+ refute include_type?(response['included'], 'roles')
187
+ end
188
+
189
+ def test_render_collection_with_missing_nested_has_many_include
190
+ get '/render_collection_with_missing_nested_has_many_include'
191
+ response = JSON.parse(@response.body)
192
+ assert response.key? 'included'
193
+ assert include_type?(response['included'], 'roles')
194
+ end
195
+
196
+ def include_type?(collection, value)
197
+ collection.detect { |i| i['type'] == value }
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,116 @@
1
+ require 'test_helper'
2
+ require 'will_paginate/array'
3
+ require 'kaminari'
4
+ require 'kaminari/hooks'
5
+ ::Kaminari::Hooks.init
6
+
7
+ module ActionController
8
+ module Serialization
9
+ class JsonApi
10
+ class PaginationTest < ActionController::TestCase
11
+ KAMINARI_URI = 'http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_kaminari'.freeze
12
+ WILL_PAGINATE_URI = 'http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate'.freeze
13
+
14
+ class PaginationTestController < ActionController::Base
15
+ def setup
16
+ @array = [
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
+ ]
21
+ end
22
+
23
+ def using_kaminari
24
+ setup
25
+ Kaminari.paginate_array(@array).page(params[:page][:number]).per(params[:page][:size])
26
+ end
27
+
28
+ def using_will_paginate
29
+ setup
30
+ @array.paginate(page: params[:page][:number], per_page: params[:page][:size])
31
+ end
32
+
33
+ def render_pagination_using_kaminari
34
+ render json: using_kaminari, adapter: :json_api
35
+ end
36
+
37
+ def render_pagination_using_will_paginate
38
+ render json: using_will_paginate, adapter: :json_api
39
+ end
40
+
41
+ def render_array_without_pagination_links
42
+ setup
43
+ render json: @array, adapter: :json_api
44
+ end
45
+ end
46
+
47
+ tests PaginationTestController
48
+
49
+ def test_render_pagination_links_with_will_paginate
50
+ expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
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
+
56
+ get :render_pagination_using_will_paginate, params: { page: { number: 2, size: 1 } }
57
+ response = JSON.parse(@response.body)
58
+ assert_equal expected_links, response['links']
59
+ end
60
+
61
+ def test_render_only_last_and_next_pagination_links
62
+ expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
63
+ 'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
64
+ 'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2" }
65
+ get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 } }
66
+ response = JSON.parse(@response.body)
67
+ assert_equal expected_links, response['links']
68
+ end
69
+
70
+ def test_render_pagination_links_with_kaminari
71
+ expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
72
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
73
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
74
+ 'next' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
75
+ 'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
76
+ get :render_pagination_using_kaminari, params: { page: { number: 2, size: 1 } }
77
+ response = JSON.parse(@response.body)
78
+ assert_equal expected_links, response['links']
79
+ end
80
+
81
+ def test_render_only_prev_and_first_pagination_links
82
+ expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
83
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
84
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1" }
85
+ get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
86
+ response = JSON.parse(@response.body)
87
+ assert_equal expected_links, response['links']
88
+ end
89
+
90
+ def test_render_only_last_and_next_pagination_links_with_additional_params
91
+ expected_links = { 'self' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
92
+ 'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
93
+ 'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional" }
94
+ get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
95
+ response = JSON.parse(@response.body)
96
+ assert_equal expected_links, response['links']
97
+ end
98
+
99
+ def test_render_only_prev_and_first_pagination_links_with_additional_params
100
+ expected_links = { 'self' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional",
101
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
102
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional" }
103
+ get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
104
+ response = JSON.parse(@response.body)
105
+ assert_equal expected_links, response['links']
106
+ end
107
+
108
+ def test_array_without_pagination_links
109
+ get :render_array_without_pagination_links, params: { page: { number: 2, size: 1 } }
110
+ response = JSON.parse(@response.body)
111
+ refute response.key? 'links'
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,189 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class JsonApi
6
+ class KeyTransformTest < ActionController::TestCase
7
+ class KeyTransformTestController < ActionController::Base
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
19
+ class PostSerializer < ActiveModel::Serializer
20
+ type 'posts'
21
+ attributes :title, :body, :publish_at
22
+ belongs_to :author
23
+ has_many :top_comments
24
+
25
+ link(:post_authors) { 'https://example.com/post_authors' }
26
+
27
+ meta do
28
+ {
29
+ rating: 5,
30
+ favorite_count: 10
31
+ }
32
+ end
33
+ end
34
+
35
+ class AuthorSerializer < ActiveModel::Serializer
36
+ type 'authors'
37
+ attributes :first_name, :last_name
38
+ end
39
+
40
+ class TopCommentSerializer < ActiveModel::Serializer
41
+ type 'top_comments'
42
+ attributes :body
43
+ belongs_to :author
44
+ end
45
+
46
+ def setup_post
47
+ ActionController::Base.cache_store.clear
48
+ @author = Author.new(id: 1, first_name: 'Bob', last_name: 'Jones')
49
+ @comment1 = TopComment.new(id: 7, body: 'cool', author: @author)
50
+ @comment2 = TopComment.new(id: 12, body: 'awesome', author: @author)
51
+ @post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1',
52
+ author: @author, top_comments: [@comment1, @comment2],
53
+ publish_at: '2020-03-16T03:55:25.291Z')
54
+ @comment1.post = @post
55
+ @comment2.post = @post
56
+ end
57
+
58
+ def render_resource_with_transform
59
+ setup_post
60
+ render json: @post, serializer: PostSerializer, adapter: :json_api,
61
+ key_transform: :camel
62
+ end
63
+
64
+ def render_resource_with_transform_nil
65
+ setup_post
66
+ render json: @post, serializer: PostSerializer, adapter: :json_api,
67
+ key_transform: nil
68
+ end
69
+
70
+ def render_resource_with_transform_with_global_config
71
+ old_transform = ActiveModelSerializers.config.key_transform
72
+ setup_post
73
+ ActiveModelSerializers.config.key_transform = :camel_lower
74
+ render json: @post, serializer: PostSerializer, adapter: :json_api
75
+ ensure
76
+ ActiveModelSerializers.config.key_transform = old_transform
77
+ end
78
+ end
79
+
80
+ tests KeyTransformTestController
81
+
82
+ def test_render_resource_with_transform
83
+ get :render_resource_with_transform
84
+ response = JSON.parse(@response.body)
85
+ expected = {
86
+ 'Data' => {
87
+ 'Id' => '1337',
88
+ 'Type' => 'Posts',
89
+ 'Attributes' => {
90
+ 'Title' => 'Title 1',
91
+ 'Body' => 'Body 1',
92
+ 'PublishAt' => '2020-03-16T03:55:25.291Z'
93
+ },
94
+ 'Relationships' => {
95
+ 'Author' => {
96
+ 'Data' => {
97
+ 'Id' => '1',
98
+ 'Type' => 'Authors'
99
+ }
100
+ },
101
+ 'TopComments' => {
102
+ 'Data' => [
103
+ { 'Id' => '7', 'Type' => 'TopComments' },
104
+ { 'Id' => '12', 'Type' => 'TopComments' }
105
+ ]
106
+ }
107
+ },
108
+ 'Links' => {
109
+ 'PostAuthors' => 'https://example.com/post_authors'
110
+ },
111
+ 'Meta' => { 'Rating' => 5, 'FavoriteCount' => 10 }
112
+ }
113
+ }
114
+ assert_equal expected, response
115
+ end
116
+
117
+ def test_render_resource_with_transform_nil
118
+ get :render_resource_with_transform_nil
119
+ response = JSON.parse(@response.body)
120
+ expected = {
121
+ 'data' => {
122
+ 'id' => '1337',
123
+ 'type' => 'posts',
124
+ 'attributes' => {
125
+ 'title' => 'Title 1',
126
+ 'body' => 'Body 1',
127
+ 'publish-at' => '2020-03-16T03:55:25.291Z'
128
+ },
129
+ 'relationships' => {
130
+ 'author' => {
131
+ 'data' => {
132
+ 'id' => '1',
133
+ 'type' => 'authors'
134
+ }
135
+ },
136
+ 'top-comments' => {
137
+ 'data' => [
138
+ { 'id' => '7', 'type' => 'top-comments' },
139
+ { 'id' => '12', 'type' => 'top-comments' }
140
+ ]
141
+ }
142
+ },
143
+ 'links' => {
144
+ 'post-authors' => 'https://example.com/post_authors'
145
+ },
146
+ 'meta' => { 'rating' => 5, 'favorite-count' => 10 }
147
+ }
148
+ }
149
+ assert_equal expected, response
150
+ end
151
+
152
+ def test_render_resource_with_transform_with_global_config
153
+ get :render_resource_with_transform_with_global_config
154
+ response = JSON.parse(@response.body)
155
+ expected = {
156
+ 'data' => {
157
+ 'id' => '1337',
158
+ 'type' => 'posts',
159
+ 'attributes' => {
160
+ 'title' => 'Title 1',
161
+ 'body' => 'Body 1',
162
+ 'publishAt' => '2020-03-16T03:55:25.291Z'
163
+ },
164
+ 'relationships' => {
165
+ 'author' => {
166
+ 'data' => {
167
+ 'id' => '1',
168
+ 'type' => 'authors'
169
+ }
170
+ },
171
+ 'topComments' => {
172
+ 'data' => [
173
+ { 'id' => '7', 'type' => 'topComments' },
174
+ { 'id' => '12', 'type' => 'topComments' }
175
+ ]
176
+ }
177
+ },
178
+ 'links' => {
179
+ 'postAuthors' => 'https://example.com/post_authors'
180
+ },
181
+ 'meta' => { 'rating' => 5, 'favoriteCount' => 10 }
182
+ }
183
+ }
184
+ assert_equal expected, response
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end