active_model_serializers_custom 0.10.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) 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 +109 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +63 -0
  8. data/CHANGELOG.md +727 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +74 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +305 -0
  14. data/Rakefile +76 -0
  15. data/active_model_serializers.gemspec +64 -0
  16. data/appveyor.yml +28 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/rubocop +38 -0
  20. data/bin/serve_benchmark +39 -0
  21. data/docs/README.md +41 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +269 -0
  24. data/docs/general/caching.md +58 -0
  25. data/docs/general/configuration_options.md +185 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/fields.md +31 -0
  28. data/docs/general/getting_started.md +133 -0
  29. data/docs/general/instrumentation.md +40 -0
  30. data/docs/general/key_transforms.md +40 -0
  31. data/docs/general/logging.md +21 -0
  32. data/docs/general/rendering.md +293 -0
  33. data/docs/general/serializers.md +495 -0
  34. data/docs/how-open-source-maintained.jpg +0 -0
  35. data/docs/howto/add_pagination_links.md +138 -0
  36. data/docs/howto/add_relationship_links.md +140 -0
  37. data/docs/howto/add_root_key.md +62 -0
  38. data/docs/howto/grape_integration.md +42 -0
  39. data/docs/howto/outside_controller_use.md +66 -0
  40. data/docs/howto/passing_arbitrary_options.md +27 -0
  41. data/docs/howto/serialize_poro.md +73 -0
  42. data/docs/howto/test.md +154 -0
  43. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  44. data/docs/integrations/ember-and-json-api.md +147 -0
  45. data/docs/integrations/grape.md +19 -0
  46. data/docs/jsonapi/errors.md +56 -0
  47. data/docs/jsonapi/schema.md +151 -0
  48. data/docs/jsonapi/schema/schema.json +366 -0
  49. data/docs/rfcs/0000-namespace.md +106 -0
  50. data/docs/rfcs/template.md +15 -0
  51. data/lib/action_controller/serialization.rb +76 -0
  52. data/lib/active_model/serializable_resource.rb +13 -0
  53. data/lib/active_model/serializer.rb +418 -0
  54. data/lib/active_model/serializer/adapter.rb +26 -0
  55. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  56. data/lib/active_model/serializer/adapter/base.rb +20 -0
  57. data/lib/active_model/serializer/adapter/json.rb +17 -0
  58. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  59. data/lib/active_model/serializer/adapter/null.rb +17 -0
  60. data/lib/active_model/serializer/array_serializer.rb +14 -0
  61. data/lib/active_model/serializer/association.rb +91 -0
  62. data/lib/active_model/serializer/attribute.rb +27 -0
  63. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +90 -0
  65. data/lib/active_model/serializer/concerns/caching.rb +304 -0
  66. data/lib/active_model/serializer/error_serializer.rb +16 -0
  67. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  68. data/lib/active_model/serializer/field.rb +92 -0
  69. data/lib/active_model/serializer/fieldset.rb +33 -0
  70. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  71. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  72. data/lib/active_model/serializer/lazy_association.rb +99 -0
  73. data/lib/active_model/serializer/link.rb +23 -0
  74. data/lib/active_model/serializer/lint.rb +152 -0
  75. data/lib/active_model/serializer/null.rb +19 -0
  76. data/lib/active_model/serializer/reflection.rb +212 -0
  77. data/lib/active_model/serializer/version.rb +7 -0
  78. data/lib/active_model_serializers.rb +63 -0
  79. data/lib/active_model_serializers/adapter.rb +100 -0
  80. data/lib/active_model_serializers/adapter/attributes.rb +15 -0
  81. data/lib/active_model_serializers/adapter/base.rb +85 -0
  82. data/lib/active_model_serializers/adapter/json.rb +23 -0
  83. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  92. data/lib/active_model_serializers/adapter/null.rb +11 -0
  93. data/lib/active_model_serializers/callbacks.rb +57 -0
  94. data/lib/active_model_serializers/deprecate.rb +56 -0
  95. data/lib/active_model_serializers/deserialization.rb +17 -0
  96. data/lib/active_model_serializers/json_pointer.rb +16 -0
  97. data/lib/active_model_serializers/logging.rb +124 -0
  98. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  99. data/lib/active_model_serializers/model.rb +132 -0
  100. data/lib/active_model_serializers/railtie.rb +52 -0
  101. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  102. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  103. data/lib/active_model_serializers/serialization_context.rb +41 -0
  104. data/lib/active_model_serializers/test.rb +9 -0
  105. data/lib/active_model_serializers/test/schema.rb +140 -0
  106. data/lib/active_model_serializers/test/serializer.rb +127 -0
  107. data/lib/generators/rails/USAGE +6 -0
  108. data/lib/generators/rails/resource_override.rb +12 -0
  109. data/lib/generators/rails/serializer_generator.rb +38 -0
  110. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  111. data/lib/grape/active_model_serializers.rb +18 -0
  112. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  113. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  114. data/lib/tasks/rubocop.rake +55 -0
  115. data/test/action_controller/adapter_selector_test.rb +64 -0
  116. data/test/action_controller/explicit_serializer_test.rb +137 -0
  117. data/test/action_controller/json/include_test.rb +248 -0
  118. data/test/action_controller/json_api/deserialization_test.rb +114 -0
  119. data/test/action_controller/json_api/errors_test.rb +42 -0
  120. data/test/action_controller/json_api/fields_test.rb +68 -0
  121. data/test/action_controller/json_api/linked_test.rb +204 -0
  122. data/test/action_controller/json_api/pagination_test.rb +126 -0
  123. data/test/action_controller/json_api/transform_test.rb +191 -0
  124. data/test/action_controller/lookup_proc_test.rb +51 -0
  125. data/test/action_controller/namespace_lookup_test.rb +239 -0
  126. data/test/action_controller/serialization_scope_name_test.rb +237 -0
  127. data/test/action_controller/serialization_test.rb +480 -0
  128. data/test/active_model_serializers/adapter_for_test.rb +210 -0
  129. data/test/active_model_serializers/json_pointer_test.rb +24 -0
  130. data/test/active_model_serializers/logging_test.rb +79 -0
  131. data/test/active_model_serializers/model_test.rb +144 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
  133. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  134. data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
  135. data/test/active_model_serializers/test/schema_test.rb +133 -0
  136. data/test/active_model_serializers/test/serializer_test.rb +64 -0
  137. data/test/active_record_test.rb +11 -0
  138. data/test/adapter/attributes_test.rb +42 -0
  139. data/test/adapter/deprecation_test.rb +102 -0
  140. data/test/adapter/json/belongs_to_test.rb +47 -0
  141. data/test/adapter/json/collection_test.rb +106 -0
  142. data/test/adapter/json/has_many_test.rb +55 -0
  143. data/test/adapter/json/transform_test.rb +95 -0
  144. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  145. data/test/adapter/json_api/collection_test.rb +98 -0
  146. data/test/adapter/json_api/errors_test.rb +78 -0
  147. data/test/adapter/json_api/fields_test.rb +98 -0
  148. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  149. data/test/adapter/json_api/has_many_test.rb +175 -0
  150. data/test/adapter/json_api/has_one_test.rb +82 -0
  151. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  152. data/test/adapter/json_api/json_api_test.rb +35 -0
  153. data/test/adapter/json_api/linked_test.rb +415 -0
  154. data/test/adapter/json_api/links_test.rb +112 -0
  155. data/test/adapter/json_api/pagination_links_test.rb +208 -0
  156. data/test/adapter/json_api/parse_test.rb +139 -0
  157. data/test/adapter/json_api/relationship_test.rb +399 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +102 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  160. data/test/adapter/json_api/transform_test.rb +514 -0
  161. data/test/adapter/json_api/type_test.rb +195 -0
  162. data/test/adapter/json_test.rb +48 -0
  163. data/test/adapter/null_test.rb +24 -0
  164. data/test/adapter/polymorphic_test.rb +220 -0
  165. data/test/adapter_test.rb +69 -0
  166. data/test/array_serializer_test.rb +24 -0
  167. data/test/benchmark/app.rb +67 -0
  168. data/test/benchmark/benchmarking_support.rb +69 -0
  169. data/test/benchmark/bm_active_record.rb +83 -0
  170. data/test/benchmark/bm_adapter.rb +40 -0
  171. data/test/benchmark/bm_caching.rb +121 -0
  172. data/test/benchmark/bm_lookup_chain.rb +85 -0
  173. data/test/benchmark/bm_transform.rb +47 -0
  174. data/test/benchmark/config.ru +3 -0
  175. data/test/benchmark/controllers.rb +85 -0
  176. data/test/benchmark/fixtures.rb +221 -0
  177. data/test/cache_test.rb +717 -0
  178. data/test/collection_serializer_test.rb +129 -0
  179. data/test/fixtures/active_record.rb +115 -0
  180. data/test/fixtures/poro.rb +227 -0
  181. data/test/generators/scaffold_controller_generator_test.rb +26 -0
  182. data/test/generators/serializer_generator_test.rb +77 -0
  183. data/test/grape_test.rb +198 -0
  184. data/test/lint_test.rb +51 -0
  185. data/test/logger_test.rb +22 -0
  186. data/test/poro_test.rb +11 -0
  187. data/test/serializable_resource_test.rb +81 -0
  188. data/test/serializers/association_macros_test.rb +39 -0
  189. data/test/serializers/associations_test.rb +520 -0
  190. data/test/serializers/attribute_test.rb +155 -0
  191. data/test/serializers/attributes_test.rb +54 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +172 -0
  193. data/test/serializers/configuration_test.rb +34 -0
  194. data/test/serializers/fieldset_test.rb +16 -0
  195. data/test/serializers/meta_test.rb +204 -0
  196. data/test/serializers/options_test.rb +34 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
  198. data/test/serializers/reflection_test.rb +481 -0
  199. data/test/serializers/root_test.rb +23 -0
  200. data/test/serializers/serialization_test.rb +57 -0
  201. data/test/serializers/serializer_for_test.rb +138 -0
  202. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  203. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  204. data/test/support/isolated_unit.rb +86 -0
  205. data/test/support/rails5_shims.rb +55 -0
  206. data/test/support/rails_app.rb +40 -0
  207. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  208. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  209. data/test/support/schemas/custom/show.json +7 -0
  210. data/test/support/schemas/hyper_schema.json +93 -0
  211. data/test/support/schemas/render_using_json_api.json +43 -0
  212. data/test/support/schemas/simple_json_pointers.json +10 -0
  213. data/test/support/serialization_testing.rb +81 -0
  214. data/test/test_helper.rb +72 -0
  215. metadata +622 -0
@@ -0,0 +1,237 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module SerializationScopeTesting
6
+ class User < ActiveModelSerializers::Model
7
+ attributes :id, :name, :admin
8
+ def admin?
9
+ admin
10
+ end
11
+ end
12
+ class Comment < ActiveModelSerializers::Model
13
+ attributes :id, :body
14
+ end
15
+ class Post < ActiveModelSerializers::Model
16
+ attributes :id, :title, :body, :comments
17
+ end
18
+ class PostSerializer < ActiveModel::Serializer
19
+ attributes :id, :title, :body, :comments
20
+
21
+ def body
22
+ "The 'scope' is the 'current_user': #{scope == current_user}"
23
+ end
24
+
25
+ def comments
26
+ if current_user.admin?
27
+ [Comment.new(id: 1, body: 'Admin')]
28
+ else
29
+ [Comment.new(id: 2, body: 'Scoped')]
30
+ end
31
+ end
32
+
33
+ def json_key
34
+ 'post'
35
+ end
36
+ end
37
+ class PostTestController < ActionController::Base
38
+ attr_writer :current_user
39
+
40
+ def render_post_by_non_admin
41
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
42
+ render json: new_post, serializer: serializer, adapter: :json
43
+ end
44
+
45
+ def render_post_by_admin
46
+ self.current_user = User.new(id: 3, name: 'Pete', admin: true)
47
+ render json: new_post, serializer: serializer, adapter: :json
48
+ end
49
+
50
+ def current_user
51
+ defined?(@current_user) ? @current_user : :current_user_not_set
52
+ end
53
+
54
+ private
55
+
56
+ def new_post
57
+ Post.new(id: 4, title: 'Title')
58
+ end
59
+
60
+ def serializer
61
+ PostSerializer
62
+ end
63
+ end
64
+ class PostViewContextSerializer < PostSerializer
65
+ def body
66
+ "The 'scope' is the 'view_context': #{scope == view_context}"
67
+ end
68
+
69
+ def comments
70
+ if view_context.controller.current_user.admin?
71
+ [Comment.new(id: 1, body: 'Admin')]
72
+ else
73
+ [Comment.new(id: 2, body: 'Scoped')]
74
+ end
75
+ end
76
+ end
77
+ class DefaultScopeTest < ActionController::TestCase
78
+ tests PostTestController
79
+
80
+ def test_default_serialization_scope
81
+ assert_equal :current_user, @controller._serialization_scope
82
+ end
83
+
84
+ def test_default_serialization_scope_object
85
+ assert_equal :current_user_not_set, @controller.current_user
86
+ assert_equal :current_user_not_set, @controller.serialization_scope
87
+ end
88
+
89
+ def test_default_scope_non_admin
90
+ get :render_post_by_non_admin
91
+ expected_json = {
92
+ post: {
93
+ id: 4,
94
+ title: 'Title',
95
+ body: "The 'scope' is the 'current_user': true",
96
+ comments: [
97
+ { id: 2, body: 'Scoped' }
98
+ ]
99
+ }
100
+ }.to_json
101
+ assert_equal expected_json, @response.body
102
+ end
103
+
104
+ def test_default_scope_admin
105
+ get :render_post_by_admin
106
+ expected_json = {
107
+ post: {
108
+ id: 4,
109
+ title: 'Title',
110
+ body: "The 'scope' is the 'current_user': true",
111
+ comments: [
112
+ { id: 1, body: 'Admin' }
113
+ ]
114
+ }
115
+ }.to_json
116
+ assert_equal expected_json, @response.body
117
+ end
118
+ end
119
+ class SerializationScopeTest < ActionController::TestCase
120
+ class PostViewContextTestController < PostTestController
121
+ serialization_scope :view_context
122
+
123
+ private
124
+
125
+ def serializer
126
+ PostViewContextSerializer
127
+ end
128
+ end
129
+ tests PostViewContextTestController
130
+
131
+ def test_defined_serialization_scope
132
+ assert_equal :view_context, @controller._serialization_scope
133
+ end
134
+
135
+ def test_defined_serialization_scope_object
136
+ assert_equal @controller.view_context.controller, @controller.serialization_scope.controller
137
+ end
138
+
139
+ def test_serialization_scope_non_admin
140
+ get :render_post_by_non_admin
141
+ expected_json = {
142
+ post: {
143
+ id: 4,
144
+ title: 'Title',
145
+ body: "The 'scope' is the 'view_context': true",
146
+ comments: [
147
+ { id: 2, body: 'Scoped' }
148
+ ]
149
+ }
150
+ }.to_json
151
+ assert_equal expected_json, @response.body
152
+ end
153
+
154
+ def test_serialization_scope_admin
155
+ get :render_post_by_admin
156
+ expected_json = {
157
+ post: {
158
+ id: 4,
159
+ title: 'Title',
160
+ body: "The 'scope' is the 'view_context': true",
161
+ comments: [
162
+ { id: 1, body: 'Admin' }
163
+ ]
164
+ }
165
+ }.to_json
166
+ assert_equal expected_json, @response.body
167
+ end
168
+ end
169
+ class NilSerializationScopeTest < ActionController::TestCase
170
+ class PostViewContextTestController < ActionController::Base
171
+ serialization_scope nil
172
+
173
+ attr_accessor :current_user
174
+
175
+ def render_post_with_no_scope
176
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
177
+ render json: new_post, serializer: PostSerializer, adapter: :json
178
+ end
179
+
180
+ def render_post_with_passed_in_scope
181
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
182
+ render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user, scope_name: :current_user
183
+ end
184
+
185
+ def render_post_with_passed_in_scope_without_scope_name
186
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
187
+ render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user
188
+ end
189
+
190
+ private
191
+
192
+ def new_post
193
+ Post.new(id: 4, title: 'Title')
194
+ end
195
+ end
196
+ tests PostViewContextTestController
197
+
198
+ def test_nil_serialization_scope
199
+ assert_nil @controller._serialization_scope
200
+ end
201
+
202
+ def test_nil_serialization_scope_object
203
+ assert_nil @controller.serialization_scope
204
+ end
205
+
206
+ def test_nil_scope
207
+ exception_matcher = /current_user/
208
+ exception = assert_raises(NameError) do
209
+ get :render_post_with_no_scope
210
+ end
211
+ assert_match exception_matcher, exception.message
212
+ end
213
+
214
+ def test_serialization_scope_is_and_nil_scope_passed_in_current_user
215
+ get :render_post_with_passed_in_scope
216
+ expected_json = {
217
+ post: {
218
+ id: 4,
219
+ title: 'Title',
220
+ body: "The 'scope' is the 'current_user': true",
221
+ comments: [
222
+ { id: 2, body: 'Scoped' }
223
+ ]
224
+ }
225
+ }.to_json
226
+ assert_equal expected_json, @response.body
227
+ end
228
+
229
+ def test_serialization_scope_is_nil_and_scope_passed_in_current_user_without_scope_name
230
+ exception_matcher = /current_user/
231
+ exception = assert_raises(NameError) do
232
+ get :render_post_with_passed_in_scope_without_scope_name
233
+ end
234
+ assert_match exception_matcher, exception.message
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,480 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActionController
6
+ module Serialization
7
+ class ImplicitSerializerTest < ActionController::TestCase
8
+ class ImplicitSerializationTestController < ActionController::Base
9
+ include SerializationTesting
10
+ def render_using_implicit_serializer
11
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
12
+ render json: @profile
13
+ end
14
+
15
+ def render_using_default_adapter_root
16
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
17
+ render json: @profile
18
+ end
19
+
20
+ def render_array_using_custom_root
21
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
22
+ render json: [@profile], root: 'custom_root'
23
+ end
24
+
25
+ def render_array_that_is_empty_using_custom_root
26
+ render json: [], root: 'custom_root'
27
+ end
28
+
29
+ def render_object_using_custom_root
30
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
31
+ render json: @profile, root: 'custom_root'
32
+ end
33
+
34
+ def render_array_using_implicit_serializer
35
+ array = [
36
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
37
+ Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2')
38
+ ]
39
+ render json: array
40
+ end
41
+
42
+ def render_array_using_implicit_serializer_and_meta
43
+ @profiles = [
44
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
45
+ ]
46
+ render json: @profiles, meta: { total: 10 }
47
+ end
48
+
49
+ def render_array_using_implicit_serializer_and_links
50
+ with_adapter ActiveModelSerializers::Adapter::JsonApi do
51
+ @profiles = [
52
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
53
+ ]
54
+
55
+ render json: @profiles, links: { self: 'http://example.com/api/profiles/1' }
56
+ end
57
+ end
58
+
59
+ def render_object_with_cache_enabled
60
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
61
+ @author = Author.new(id: 1, name: 'Joao Moura.')
62
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [@comment], author: @author)
63
+
64
+ generate_cached_serializer(@post)
65
+
66
+ @post.title = 'ZOMG a New Post'
67
+ render json: @post
68
+ end
69
+
70
+ def render_json_object_without_serializer
71
+ render json: { error: 'Result is Invalid' }
72
+ end
73
+
74
+ def render_json_array_object_without_serializer
75
+ render json: [{ error: 'Result is Invalid' }]
76
+ end
77
+
78
+ def update_and_render_object_with_cache_enabled
79
+ @post.updated_at = Time.zone.now
80
+
81
+ generate_cached_serializer(@post)
82
+ render json: @post
83
+ end
84
+
85
+ def render_object_expired_with_cache_enabled
86
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
87
+ author = Author.new(id: 1, name: 'Joao Moura.')
88
+ post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [comment], author: author)
89
+
90
+ generate_cached_serializer(post)
91
+
92
+ post.title = 'ZOMG a New Post'
93
+
94
+ expires_in = [
95
+ PostSerializer._cache_options[:expires_in],
96
+ CommentSerializer._cache_options[:expires_in]
97
+ ].max + 200
98
+
99
+ Timecop.travel(Time.zone.now + expires_in) do
100
+ render json: post
101
+ end
102
+ end
103
+
104
+ def render_changed_object_with_cache_enabled
105
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
106
+ author = Author.new(id: 1, name: 'Joao Moura.')
107
+ post = Post.new(id: 1, title: 'ZOMG a New Post', body: 'Body', comments: [comment], author: author)
108
+
109
+ render json: post
110
+ end
111
+
112
+ def render_fragment_changed_object_with_only_cache_enabled
113
+ author = Author.new(id: 1, name: 'Joao Moura.')
114
+ role = Role.new(id: 42, name: 'ZOMG A ROLE', description: 'DESCRIPTION HERE', author: author)
115
+
116
+ generate_cached_serializer(role)
117
+ role.name = 'lol'
118
+ role.description = 'HUEHUEBRBR'
119
+
120
+ render json: role
121
+ end
122
+
123
+ def render_fragment_changed_object_with_except_cache_enabled
124
+ author = Author.new(id: 1, name: 'Joao Moura.')
125
+ bio = Bio.new(id: 42, content: 'ZOMG A ROLE', rating: 5, author: author)
126
+
127
+ generate_cached_serializer(bio)
128
+ bio.content = 'lol'
129
+ bio.rating = 0
130
+
131
+ render json: bio
132
+ end
133
+
134
+ def render_fragment_changed_object_with_relationship
135
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
136
+ comment2 = Comment.new(id: 1, body: 'ZOMG AN UPDATED-BUT-NOT-CACHE-EXPIRED COMMENT')
137
+ like = Like.new(id: 1, likeable: comment, time: 3.days.ago)
138
+
139
+ generate_cached_serializer(like)
140
+ like.likeable = comment2
141
+ like.time = Time.zone.now.to_s
142
+
143
+ render json: like
144
+ end
145
+ end
146
+
147
+ tests ImplicitSerializationTestController
148
+
149
+ # We just have Null for now, this will change
150
+ def test_render_using_implicit_serializer
151
+ get :render_using_implicit_serializer
152
+
153
+ expected = {
154
+ name: 'Name 1',
155
+ description: 'Description 1'
156
+ }
157
+
158
+ assert_equal 'application/json', @response.content_type
159
+ assert_equal expected.to_json, @response.body
160
+ end
161
+
162
+ def test_render_using_default_root
163
+ with_adapter :json_api do
164
+ get :render_using_default_adapter_root
165
+ end
166
+ expected = {
167
+ data: {
168
+ id: @controller.instance_variable_get(:@profile).id.to_s,
169
+ type: 'profiles',
170
+ attributes: {
171
+ name: 'Name 1',
172
+ description: 'Description 1'
173
+ }
174
+ }
175
+ }
176
+
177
+ assert_equal 'application/json', @response.content_type
178
+ assert_equal expected.to_json, @response.body
179
+ end
180
+
181
+ def test_render_array_using_custom_root
182
+ with_adapter :json do
183
+ get :render_array_using_custom_root
184
+ end
185
+ expected = { custom_root: [{ name: 'Name 1', description: 'Description 1' }] }
186
+ assert_equal 'application/json', @response.content_type
187
+ assert_equal expected.to_json, @response.body
188
+ end
189
+
190
+ def test_render_array_that_is_empty_using_custom_root
191
+ with_adapter :json do
192
+ get :render_array_that_is_empty_using_custom_root
193
+ end
194
+
195
+ expected = { custom_root: [] }
196
+ assert_equal 'application/json', @response.content_type
197
+ assert_equal expected.to_json, @response.body
198
+ end
199
+
200
+ def test_render_object_using_custom_root
201
+ with_adapter :json do
202
+ get :render_object_using_custom_root
203
+ end
204
+
205
+ expected = { custom_root: { name: 'Name 1', description: 'Description 1' } }
206
+ assert_equal 'application/json', @response.content_type
207
+ assert_equal expected.to_json, @response.body
208
+ end
209
+
210
+ def test_render_json_object_without_serializer
211
+ get :render_json_object_without_serializer
212
+
213
+ assert_equal 'application/json', @response.content_type
214
+ expected_body = { error: 'Result is Invalid' }
215
+ assert_equal expected_body.to_json, @response.body
216
+ end
217
+
218
+ def test_render_json_array_object_without_serializer
219
+ get :render_json_array_object_without_serializer
220
+
221
+ assert_equal 'application/json', @response.content_type
222
+ expected_body = [{ error: 'Result is Invalid' }]
223
+ assert_equal expected_body.to_json, @response.body
224
+ end
225
+
226
+ def test_render_array_using_implicit_serializer
227
+ get :render_array_using_implicit_serializer
228
+ assert_equal 'application/json', @response.content_type
229
+
230
+ expected = [
231
+ {
232
+ name: 'Name 1',
233
+ description: 'Description 1'
234
+ },
235
+ {
236
+ name: 'Name 2',
237
+ description: 'Description 2'
238
+ }
239
+ ]
240
+
241
+ assert_equal expected.to_json, @response.body
242
+ end
243
+
244
+ def test_render_array_using_implicit_serializer_and_meta
245
+ with_adapter :json_api do
246
+ get :render_array_using_implicit_serializer_and_meta
247
+ end
248
+ expected = {
249
+ data: [
250
+ {
251
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
252
+ type: 'profiles',
253
+ attributes: {
254
+ name: 'Name 1',
255
+ description: 'Description 1'
256
+ }
257
+ }
258
+ ],
259
+ meta: {
260
+ total: 10
261
+ }
262
+ }
263
+
264
+ assert_equal 'application/json', @response.content_type
265
+ assert_equal expected.to_json, @response.body
266
+ end
267
+
268
+ def test_render_array_using_implicit_serializer_and_links
269
+ get :render_array_using_implicit_serializer_and_links
270
+
271
+ expected = {
272
+ data: [
273
+ {
274
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
275
+ type: 'profiles',
276
+ attributes: {
277
+ name: 'Name 1',
278
+ description: 'Description 1'
279
+ }
280
+ }
281
+ ],
282
+ links: {
283
+ self: 'http://example.com/api/profiles/1'
284
+ }
285
+ }
286
+
287
+ assert_equal 'application/json', @response.content_type
288
+ assert_equal expected.to_json, @response.body
289
+ end
290
+
291
+ def test_render_with_cache_enable
292
+ expected = {
293
+ id: 1,
294
+ title: 'New Post',
295
+ body: 'Body',
296
+ comments: [
297
+ {
298
+ id: 1,
299
+ body: 'ZOMG A COMMENT'
300
+ }
301
+ ],
302
+ blog: {
303
+ id: 999,
304
+ name: 'Custom blog'
305
+ },
306
+ author: {
307
+ id: 1,
308
+ name: 'Joao Moura.'
309
+ }
310
+ }
311
+
312
+ ActionController::Base.cache_store.clear
313
+ Timecop.freeze(Time.zone.now) do
314
+ get :render_object_with_cache_enabled
315
+
316
+ assert_equal 'application/json', @response.content_type
317
+ assert_equal expected.to_json, @response.body
318
+
319
+ get :render_changed_object_with_cache_enabled
320
+ assert_equal expected.to_json, @response.body
321
+ end
322
+
323
+ ActionController::Base.cache_store.clear
324
+ get :render_changed_object_with_cache_enabled
325
+ assert_not_equal expected.to_json, @response.body
326
+ end
327
+
328
+ def test_render_with_cache_enable_and_expired
329
+ ActionController::Base.cache_store.clear
330
+ get :render_object_expired_with_cache_enabled
331
+
332
+ expected = {
333
+ id: 1,
334
+ title: 'ZOMG a New Post',
335
+ body: 'Body',
336
+ comments: [
337
+ {
338
+ id: 1,
339
+ body: 'ZOMG A COMMENT'
340
+ }
341
+ ],
342
+ blog: {
343
+ id: 999,
344
+ name: 'Custom blog'
345
+ },
346
+ author: {
347
+ id: 1,
348
+ name: 'Joao Moura.'
349
+ }
350
+ }
351
+
352
+ assert_equal 'application/json', @response.content_type
353
+ actual = @response.body
354
+ expected = expected.to_json
355
+ if ENV['APPVEYOR'] && actual != expected
356
+ skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
357
+ else
358
+ assert_equal actual, expected
359
+ end
360
+ end
361
+
362
+ def test_render_with_fragment_only_cache_enable
363
+ ActionController::Base.cache_store.clear
364
+ get :render_fragment_changed_object_with_only_cache_enabled
365
+ response = JSON.parse(@response.body)
366
+
367
+ assert_equal 'application/json', @response.content_type
368
+ assert_equal 'ZOMG A ROLE', response['name']
369
+ assert_equal 'HUEHUEBRBR', response['description']
370
+ end
371
+
372
+ def test_render_with_fragment_except_cache_enable
373
+ ActionController::Base.cache_store.clear
374
+ get :render_fragment_changed_object_with_except_cache_enabled
375
+ response = JSON.parse(@response.body)
376
+
377
+ assert_equal 'application/json', @response.content_type
378
+ assert_equal 5, response['rating']
379
+ assert_equal 'lol', response['content']
380
+ end
381
+
382
+ def test_render_fragment_changed_object_with_relationship
383
+ ActionController::Base.cache_store.clear
384
+
385
+ Timecop.freeze(Time.zone.now) do
386
+ get :render_fragment_changed_object_with_relationship
387
+ response = JSON.parse(@response.body)
388
+
389
+ expected_return = {
390
+ 'id' => 1,
391
+ 'time' => Time.zone.now.to_s,
392
+ 'likeable' => {
393
+ 'id' => 1,
394
+ 'body' => 'ZOMG A COMMENT'
395
+ }
396
+ }
397
+
398
+ assert_equal 'application/json', @response.content_type
399
+ assert_equal expected_return, response
400
+ end
401
+ end
402
+
403
+ def test_cache_expiration_on_update
404
+ ActionController::Base.cache_store.clear
405
+ get :render_object_with_cache_enabled
406
+
407
+ expected = {
408
+ id: 1,
409
+ title: 'ZOMG a New Post',
410
+ body: 'Body',
411
+ comments: [
412
+ {
413
+ id: 1,
414
+ body: 'ZOMG A COMMENT'
415
+ }
416
+ ],
417
+ blog: {
418
+ id: 999,
419
+ name: 'Custom blog'
420
+ },
421
+ author: {
422
+ id: 1,
423
+ name: 'Joao Moura.'
424
+ }
425
+ }
426
+
427
+ get :update_and_render_object_with_cache_enabled
428
+
429
+ assert_equal 'application/json', @response.content_type
430
+ actual = @response.body
431
+ expected = expected.to_json
432
+ if ENV['APPVEYOR'] && actual != expected
433
+ skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
434
+ else
435
+ assert_equal actual, expected
436
+ end
437
+ end
438
+
439
+ def test_warn_overridding_use_adapter_as_falsy_on_controller_instance
440
+ controller = Class.new(ImplicitSerializationTestController) do
441
+ def use_adapter?
442
+ false
443
+ end
444
+ end.new
445
+ assert_output(nil, /adapter: false/) do
446
+ controller.get_serializer(Profile.new)
447
+ end
448
+ end
449
+
450
+ def test_dont_warn_overridding_use_adapter_as_truthy_on_controller_instance
451
+ controller = Class.new(ImplicitSerializationTestController) do
452
+ def use_adapter?
453
+ true
454
+ end
455
+ end.new
456
+ assert_output(nil, '') do
457
+ controller.get_serializer(Profile.new)
458
+ end
459
+ end
460
+
461
+ def test_render_event_is_emitted
462
+ subscriber = ::ActiveSupport::Notifications.subscribe('render.active_model_serializers') do |subscribed_event|
463
+ @subscribed_event = subscribed_event
464
+ end
465
+
466
+ get :render_using_implicit_serializer
467
+
468
+ subscribed_event_name =
469
+ if @subscribed_event.is_a?(String)
470
+ @subscribed_event
471
+ else
472
+ @subscribed_event.name # is a ActiveSupport::Notifications::Event
473
+ end
474
+ assert_equal 'render.active_model_serializers', subscribed_event_name
475
+ ensure
476
+ ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
477
+ end
478
+ end
479
+ end
480
+ end