active_model_serializers 0.8.3 → 0.10.0

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