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,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,181 @@
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
+ Post = Class.new(::Model)
9
+ class PostSerializer < ActiveModel::Serializer
10
+ type 'posts'
11
+ attributes :title, :body, :publish_at
12
+ belongs_to :author
13
+ has_many :top_comments
14
+
15
+ link(:post_authors) { 'https://example.com/post_authors' }
16
+
17
+ meta do
18
+ {
19
+ rating: 5,
20
+ favorite_count: 10
21
+ }
22
+ end
23
+ end
24
+
25
+ Author = Class.new(::Model)
26
+ class AuthorSerializer < ActiveModel::Serializer
27
+ type 'authors'
28
+ attributes :first_name, :last_name
29
+ end
30
+
31
+ TopComment = Class.new(::Model)
32
+ class TopCommentSerializer < ActiveModel::Serializer
33
+ type 'top_comments'
34
+ attributes :body
35
+ belongs_to :author
36
+ end
37
+
38
+ def setup_post
39
+ ActionController::Base.cache_store.clear
40
+ @author = Author.new(id: 1, first_name: 'Bob', last_name: 'Jones')
41
+ @comment1 = TopComment.new(id: 7, body: 'cool', author: @author)
42
+ @comment2 = TopComment.new(id: 12, body: 'awesome', author: @author)
43
+ @post = Post.new(id: 1337, title: 'Title 1', body: 'Body 1',
44
+ author: @author, top_comments: [@comment1, @comment2],
45
+ publish_at: '2020-03-16T03:55:25.291Z')
46
+ @comment1.post = @post
47
+ @comment2.post = @post
48
+ end
49
+
50
+ def render_resource_with_transform
51
+ setup_post
52
+ render json: @post, serializer: PostSerializer, adapter: :json_api,
53
+ key_transform: :camel
54
+ end
55
+
56
+ def render_resource_with_transform_nil
57
+ setup_post
58
+ render json: @post, serializer: PostSerializer, adapter: :json_api,
59
+ key_transform: nil
60
+ end
61
+
62
+ def render_resource_with_transform_with_global_config
63
+ old_transform = ActiveModelSerializers.config.key_transform
64
+ setup_post
65
+ ActiveModelSerializers.config.key_transform = :camel_lower
66
+ render json: @post, serializer: PostSerializer, adapter: :json_api
67
+ ensure
68
+ ActiveModelSerializers.config.key_transform = old_transform
69
+ end
70
+ end
71
+
72
+ tests KeyTransformTestController
73
+
74
+ def test_render_resource_with_transform
75
+ get :render_resource_with_transform
76
+ response = JSON.parse(@response.body)
77
+ expected = {
78
+ 'Data' => {
79
+ 'Id' => '1337',
80
+ 'Type' => 'Posts',
81
+ 'Attributes' => {
82
+ 'Title' => 'Title 1',
83
+ 'Body' => 'Body 1',
84
+ 'PublishAt' => '2020-03-16T03:55:25.291Z'
85
+ },
86
+ 'Relationships' => {
87
+ 'Author' => {
88
+ 'Data' => {
89
+ 'Id' => '1',
90
+ 'Type' => 'Authors'
91
+ }
92
+ },
93
+ 'TopComments' => {
94
+ 'Data' => [
95
+ { 'Id' => '7', 'Type' => 'TopComments' },
96
+ { 'Id' => '12', 'Type' => 'TopComments' }
97
+ ]
98
+ }
99
+ },
100
+ 'Links' => {
101
+ 'PostAuthors' => 'https://example.com/post_authors'
102
+ },
103
+ 'Meta' => { 'Rating' => 5, 'FavoriteCount' => 10 }
104
+ }
105
+ }
106
+ assert_equal expected, response
107
+ end
108
+
109
+ def test_render_resource_with_transform_nil
110
+ get :render_resource_with_transform_nil
111
+ response = JSON.parse(@response.body)
112
+ expected = {
113
+ 'data' => {
114
+ 'id' => '1337',
115
+ 'type' => 'posts',
116
+ 'attributes' => {
117
+ 'title' => 'Title 1',
118
+ 'body' => 'Body 1',
119
+ 'publish-at' => '2020-03-16T03:55:25.291Z'
120
+ },
121
+ 'relationships' => {
122
+ 'author' => {
123
+ 'data' => {
124
+ 'id' => '1',
125
+ 'type' => 'authors'
126
+ }
127
+ },
128
+ 'top-comments' => {
129
+ 'data' => [
130
+ { 'id' => '7', 'type' => 'top-comments' },
131
+ { 'id' => '12', 'type' => 'top-comments' }
132
+ ]
133
+ }
134
+ },
135
+ 'links' => {
136
+ 'post-authors' => 'https://example.com/post_authors'
137
+ },
138
+ 'meta' => { 'rating' => 5, 'favorite-count' => 10 }
139
+ }
140
+ }
141
+ assert_equal expected, response
142
+ end
143
+
144
+ def test_render_resource_with_transform_with_global_config
145
+ get :render_resource_with_transform_with_global_config
146
+ response = JSON.parse(@response.body)
147
+ expected = {
148
+ 'data' => {
149
+ 'id' => '1337',
150
+ 'type' => 'posts',
151
+ 'attributes' => {
152
+ 'title' => 'Title 1',
153
+ 'body' => 'Body 1',
154
+ 'publishAt' => '2020-03-16T03:55:25.291Z'
155
+ },
156
+ 'relationships' => {
157
+ 'author' => {
158
+ 'data' => {
159
+ 'id' => '1',
160
+ 'type' => 'authors'
161
+ }
162
+ },
163
+ 'topComments' => {
164
+ 'data' => [
165
+ { 'id' => '7', 'type' => 'topComments' },
166
+ { 'id' => '12', 'type' => 'topComments' }
167
+ ]
168
+ }
169
+ },
170
+ 'links' => {
171
+ 'postAuthors' => 'https://example.com/post_authors'
172
+ },
173
+ 'meta' => { 'rating' => 5, 'favoriteCount' => 10 }
174
+ }
175
+ }
176
+ assert_equal expected, response
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,229 @@
1
+ require 'test_helper'
2
+
3
+ module SerializationScopeTesting
4
+ class User < ActiveModelSerializers::Model
5
+ attr_accessor :id, :name, :admin
6
+ def admin?
7
+ admin
8
+ end
9
+ end
10
+ class Comment < ActiveModelSerializers::Model
11
+ attr_accessor :id, :body
12
+ end
13
+ class Post < ActiveModelSerializers::Model
14
+ attr_accessor :id, :title, :body, :comments
15
+ end
16
+ class PostSerializer < ActiveModel::Serializer
17
+ attributes :id, :title, :body, :comments
18
+
19
+ def body
20
+ "The 'scope' is the 'current_user': #{scope == current_user}"
21
+ end
22
+
23
+ def comments
24
+ if current_user.admin?
25
+ [Comment.new(id: 1, body: 'Admin')]
26
+ else
27
+ [Comment.new(id: 2, body: 'Scoped')]
28
+ end
29
+ end
30
+
31
+ def json_key
32
+ 'post'
33
+ end
34
+ end
35
+ class PostTestController < ActionController::Base
36
+ attr_accessor :current_user
37
+ def render_post_by_non_admin
38
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
39
+ render json: new_post, serializer: serializer, adapter: :json
40
+ end
41
+
42
+ def render_post_by_admin
43
+ self.current_user = User.new(id: 3, name: 'Pete', admin: true)
44
+ render json: new_post, serializer: serializer, adapter: :json
45
+ end
46
+
47
+ private
48
+
49
+ def new_post
50
+ Post.new(id: 4, title: 'Title')
51
+ end
52
+
53
+ def serializer
54
+ PostSerializer
55
+ end
56
+ end
57
+ class PostViewContextSerializer < PostSerializer
58
+ def body
59
+ "The 'scope' is the 'view_context': #{scope == view_context}"
60
+ end
61
+
62
+ def comments
63
+ if view_context.controller.current_user.admin?
64
+ [Comment.new(id: 1, body: 'Admin')]
65
+ else
66
+ [Comment.new(id: 2, body: 'Scoped')]
67
+ end
68
+ end
69
+ end
70
+ class DefaultScopeTest < ActionController::TestCase
71
+ tests PostTestController
72
+
73
+ def test_default_serialization_scope
74
+ assert_equal :current_user, @controller._serialization_scope
75
+ end
76
+
77
+ def test_default_serialization_scope_object
78
+ assert_equal @controller.current_user, @controller.serialization_scope
79
+ end
80
+
81
+ def test_default_scope_non_admin
82
+ get :render_post_by_non_admin
83
+ expected_json = {
84
+ post: {
85
+ id: 4,
86
+ title: 'Title',
87
+ body: "The 'scope' is the 'current_user': true",
88
+ comments: [
89
+ { id: 2, body: 'Scoped' }
90
+ ]
91
+ }
92
+ }.to_json
93
+ assert_equal expected_json, @response.body
94
+ end
95
+
96
+ def test_default_scope_admin
97
+ get :render_post_by_admin
98
+ expected_json = {
99
+ post: {
100
+ id: 4,
101
+ title: 'Title',
102
+ body: "The 'scope' is the 'current_user': true",
103
+ comments: [
104
+ { id: 1, body: 'Admin' }
105
+ ]
106
+ }
107
+ }.to_json
108
+ assert_equal expected_json, @response.body
109
+ end
110
+ end
111
+ class SerializationScopeTest < ActionController::TestCase
112
+ class PostViewContextTestController < PostTestController
113
+ serialization_scope :view_context
114
+
115
+ private
116
+
117
+ def serializer
118
+ PostViewContextSerializer
119
+ end
120
+ end
121
+ tests PostViewContextTestController
122
+
123
+ def test_defined_serialization_scope
124
+ assert_equal :view_context, @controller._serialization_scope
125
+ end
126
+
127
+ def test_defined_serialization_scope_object
128
+ assert_equal @controller.view_context.class, @controller.serialization_scope.class
129
+ end
130
+
131
+ def test_serialization_scope_non_admin
132
+ get :render_post_by_non_admin
133
+ expected_json = {
134
+ post: {
135
+ id: 4,
136
+ title: 'Title',
137
+ body: "The 'scope' is the 'view_context': true",
138
+ comments: [
139
+ { id: 2, body: 'Scoped' }
140
+ ]
141
+ }
142
+ }.to_json
143
+ assert_equal expected_json, @response.body
144
+ end
145
+
146
+ def test_serialization_scope_admin
147
+ get :render_post_by_admin
148
+ expected_json = {
149
+ post: {
150
+ id: 4,
151
+ title: 'Title',
152
+ body: "The 'scope' is the 'view_context': true",
153
+ comments: [
154
+ { id: 1, body: 'Admin' }
155
+ ]
156
+ }
157
+ }.to_json
158
+ assert_equal expected_json, @response.body
159
+ end
160
+ end
161
+ class NilSerializationScopeTest < ActionController::TestCase
162
+ class PostViewContextTestController < ActionController::Base
163
+ serialization_scope nil
164
+
165
+ attr_accessor :current_user
166
+
167
+ def render_post_with_no_scope
168
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
169
+ render json: new_post, serializer: PostSerializer, adapter: :json
170
+ end
171
+
172
+ def render_post_with_passed_in_scope
173
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
174
+ render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user, scope_name: :current_user
175
+ end
176
+
177
+ def render_post_with_passed_in_scope_without_scope_name
178
+ self.current_user = User.new(id: 3, name: 'Pete', admin: false)
179
+ render json: new_post, serializer: PostSerializer, adapter: :json, scope: current_user
180
+ end
181
+
182
+ private
183
+
184
+ def new_post
185
+ Post.new(id: 4, title: 'Title')
186
+ end
187
+ end
188
+ tests PostViewContextTestController
189
+
190
+ def test_nil_serialization_scope
191
+ assert_nil @controller._serialization_scope
192
+ end
193
+
194
+ def test_nil_serialization_scope_object
195
+ assert_nil @controller.serialization_scope
196
+ end
197
+
198
+ def test_nil_scope
199
+ exception_matcher = /current_user/
200
+ exception = assert_raises(NameError) do
201
+ get :render_post_with_no_scope
202
+ end
203
+ assert_match exception_matcher, exception.message
204
+ end
205
+
206
+ def test_serialization_scope_is_and_nil_scope_passed_in_current_user
207
+ get :render_post_with_passed_in_scope
208
+ expected_json = {
209
+ post: {
210
+ id: 4,
211
+ title: 'Title',
212
+ body: "The 'scope' is the 'current_user': true",
213
+ comments: [
214
+ { id: 2, body: 'Scoped' }
215
+ ]
216
+ }
217
+ }.to_json
218
+ assert_equal expected_json, @response.body
219
+ end
220
+
221
+ def test_serialization_scope_is_nil_and_scope_passed_in_current_user_without_scope_name
222
+ exception_matcher = /current_user/
223
+ exception = assert_raises(NameError) do
224
+ get :render_post_with_passed_in_scope_without_scope_name
225
+ end
226
+ assert_match exception_matcher, exception.message
227
+ end
228
+ end
229
+ end