active_model_serializers 0.10.0 → 0.10.9

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 (206) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +10 -5
  3. data/.travis.yml +41 -21
  4. data/CHANGELOG.md +200 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +25 -4
  7. data/README.md +166 -28
  8. data/Rakefile +5 -32
  9. data/active_model_serializers.gemspec +23 -25
  10. data/appveyor.yml +10 -6
  11. data/bin/rubocop +38 -0
  12. data/docs/README.md +2 -1
  13. data/docs/general/adapters.md +35 -11
  14. data/docs/general/caching.md +7 -1
  15. data/docs/general/configuration_options.md +86 -1
  16. data/docs/general/deserialization.md +1 -1
  17. data/docs/general/fields.md +31 -0
  18. data/docs/general/getting_started.md +1 -1
  19. data/docs/general/logging.md +7 -0
  20. data/docs/general/rendering.md +63 -25
  21. data/docs/general/serializers.md +137 -14
  22. data/docs/howto/add_pagination_links.md +16 -17
  23. data/docs/howto/add_relationship_links.md +140 -0
  24. data/docs/howto/add_root_key.md +11 -0
  25. data/docs/howto/grape_integration.md +42 -0
  26. data/docs/howto/outside_controller_use.md +12 -4
  27. data/docs/howto/passing_arbitrary_options.md +2 -2
  28. data/docs/howto/serialize_poro.md +46 -5
  29. data/docs/howto/test.md +2 -0
  30. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  31. data/docs/integrations/ember-and-json-api.md +67 -32
  32. data/docs/jsonapi/schema.md +1 -1
  33. data/lib/action_controller/serialization.rb +15 -3
  34. data/lib/active_model/serializable_resource.rb +2 -0
  35. data/lib/active_model/serializer/adapter/attributes.rb +2 -0
  36. data/lib/active_model/serializer/adapter/base.rb +4 -0
  37. data/lib/active_model/serializer/adapter/json.rb +2 -0
  38. data/lib/active_model/serializer/adapter/json_api.rb +2 -0
  39. data/lib/active_model/serializer/adapter/null.rb +2 -0
  40. data/lib/active_model/serializer/adapter.rb +2 -0
  41. data/lib/active_model/serializer/array_serializer.rb +10 -5
  42. data/lib/active_model/serializer/association.rb +64 -10
  43. data/lib/active_model/serializer/attribute.rb +2 -0
  44. data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
  45. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  46. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +87 -116
  47. data/lib/active_model/serializer/error_serializer.rb +13 -7
  48. data/lib/active_model/serializer/errors_serializer.rb +27 -20
  49. data/lib/active_model/serializer/field.rb +2 -0
  50. data/lib/active_model/serializer/fieldset.rb +2 -0
  51. data/lib/active_model/serializer/has_many_reflection.rb +5 -3
  52. data/lib/active_model/serializer/has_one_reflection.rb +3 -4
  53. data/lib/active_model/serializer/lazy_association.rb +99 -0
  54. data/lib/active_model/serializer/link.rb +23 -0
  55. data/lib/active_model/serializer/lint.rb +136 -130
  56. data/lib/active_model/serializer/null.rb +2 -0
  57. data/lib/active_model/serializer/reflection.rb +132 -67
  58. data/lib/active_model/serializer/version.rb +3 -1
  59. data/lib/active_model/serializer.rb +308 -82
  60. data/lib/active_model_serializers/adapter/attributes.rb +5 -66
  61. data/lib/active_model_serializers/adapter/base.rb +41 -39
  62. data/lib/active_model_serializers/adapter/json.rb +2 -0
  63. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
  64. data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
  65. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
  66. data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
  67. data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
  68. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +49 -21
  69. data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
  70. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
  71. data/lib/active_model_serializers/adapter/json_api.rb +84 -65
  72. data/lib/active_model_serializers/adapter/null.rb +2 -0
  73. data/lib/active_model_serializers/adapter.rb +9 -1
  74. data/lib/active_model_serializers/callbacks.rb +2 -0
  75. data/lib/active_model_serializers/deprecate.rb +3 -2
  76. data/lib/active_model_serializers/deserialization.rb +4 -0
  77. data/lib/active_model_serializers/json_pointer.rb +2 -0
  78. data/lib/active_model_serializers/logging.rb +2 -0
  79. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  80. data/lib/active_model_serializers/model.rb +111 -28
  81. data/lib/active_model_serializers/railtie.rb +7 -1
  82. data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
  83. data/lib/active_model_serializers/serializable_resource.rb +10 -7
  84. data/lib/active_model_serializers/serialization_context.rb +12 -3
  85. data/lib/active_model_serializers/test/schema.rb +4 -2
  86. data/lib/active_model_serializers/test/serializer.rb +2 -0
  87. data/lib/active_model_serializers/test.rb +2 -0
  88. data/lib/active_model_serializers.rb +35 -10
  89. data/lib/generators/rails/resource_override.rb +3 -1
  90. data/lib/generators/rails/serializer_generator.rb +6 -4
  91. data/lib/grape/active_model_serializers.rb +9 -5
  92. data/lib/grape/formatters/active_model_serializers.rb +21 -2
  93. data/lib/grape/helpers/active_model_serializers.rb +3 -0
  94. data/lib/tasks/rubocop.rake +55 -0
  95. data/test/action_controller/adapter_selector_test.rb +16 -5
  96. data/test/action_controller/explicit_serializer_test.rb +7 -4
  97. data/test/action_controller/json/include_test.rb +108 -27
  98. data/test/action_controller/json_api/deserialization_test.rb +3 -1
  99. data/test/action_controller/json_api/errors_test.rb +10 -9
  100. data/test/action_controller/json_api/fields_test.rb +68 -0
  101. data/test/action_controller/json_api/linked_test.rb +31 -24
  102. data/test/action_controller/json_api/pagination_test.rb +33 -23
  103. data/test/action_controller/json_api/transform_test.rb +13 -3
  104. data/test/action_controller/lookup_proc_test.rb +51 -0
  105. data/test/action_controller/namespace_lookup_test.rb +234 -0
  106. data/test/action_controller/serialization_scope_name_test.rb +14 -6
  107. data/test/action_controller/serialization_test.rb +23 -12
  108. data/test/active_model_serializers/adapter_for_test.rb +2 -0
  109. data/test/active_model_serializers/json_pointer_test.rb +17 -13
  110. data/test/active_model_serializers/logging_test.rb +2 -0
  111. data/test/active_model_serializers/model_test.rb +139 -4
  112. data/test/active_model_serializers/railtie_test_isolated.rb +14 -7
  113. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  114. data/test/active_model_serializers/serialization_context_test_isolated.rb +25 -10
  115. data/test/active_model_serializers/test/schema_test.rb +5 -2
  116. data/test/active_model_serializers/test/serializer_test.rb +2 -0
  117. data/test/active_record_test.rb +2 -0
  118. data/test/adapter/attributes_test.rb +42 -0
  119. data/test/adapter/deprecation_test.rb +2 -0
  120. data/test/adapter/json/belongs_to_test.rb +2 -0
  121. data/test/adapter/json/collection_test.rb +16 -0
  122. data/test/adapter/json/has_many_test.rb +12 -2
  123. data/test/adapter/json/transform_test.rb +17 -15
  124. data/test/adapter/json_api/belongs_to_test.rb +2 -0
  125. data/test/adapter/json_api/collection_test.rb +6 -3
  126. data/test/adapter/json_api/errors_test.rb +19 -19
  127. data/test/adapter/json_api/fields_test.rb +14 -3
  128. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +2 -0
  129. data/test/adapter/json_api/has_many_test.rb +51 -20
  130. data/test/adapter/json_api/has_one_test.rb +2 -0
  131. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  132. data/test/adapter/json_api/json_api_test.rb +7 -7
  133. data/test/adapter/json_api/linked_test.rb +35 -12
  134. data/test/adapter/json_api/links_test.rb +22 -3
  135. data/test/adapter/json_api/pagination_links_test.rb +55 -13
  136. data/test/adapter/json_api/parse_test.rb +3 -1
  137. data/test/adapter/json_api/relationship_test.rb +311 -73
  138. data/test/adapter/json_api/resource_meta_test.rb +5 -3
  139. data/test/adapter/json_api/toplevel_jsonapi_test.rb +2 -0
  140. data/test/adapter/json_api/transform_test.rb +265 -253
  141. data/test/adapter/json_api/type_test.rb +170 -36
  142. data/test/adapter/json_test.rb +10 -7
  143. data/test/adapter/null_test.rb +3 -2
  144. data/test/adapter/polymorphic_test.rb +54 -5
  145. data/test/adapter_test.rb +3 -1
  146. data/test/array_serializer_test.rb +2 -0
  147. data/test/benchmark/app.rb +3 -1
  148. data/test/benchmark/benchmarking_support.rb +3 -1
  149. data/test/benchmark/bm_active_record.rb +83 -0
  150. data/test/benchmark/bm_adapter.rb +40 -0
  151. data/test/benchmark/bm_caching.rb +18 -16
  152. data/test/benchmark/bm_lookup_chain.rb +85 -0
  153. data/test/benchmark/bm_transform.rb +23 -10
  154. data/test/benchmark/controllers.rb +18 -17
  155. data/test/benchmark/fixtures.rb +74 -72
  156. data/test/cache_test.rb +301 -69
  157. data/test/collection_serializer_test.rb +33 -14
  158. data/test/fixtures/active_record.rb +47 -10
  159. data/test/fixtures/poro.rb +128 -183
  160. data/test/generators/scaffold_controller_generator_test.rb +2 -0
  161. data/test/generators/serializer_generator_test.rb +25 -5
  162. data/test/grape_test.rb +172 -56
  163. data/test/lint_test.rb +3 -1
  164. data/test/logger_test.rb +15 -11
  165. data/test/poro_test.rb +2 -0
  166. data/test/serializable_resource_test.rb +20 -22
  167. data/test/serializers/association_macros_test.rb +5 -2
  168. data/test/serializers/associations_test.rb +274 -49
  169. data/test/serializers/attribute_test.rb +7 -3
  170. data/test/serializers/attributes_test.rb +3 -1
  171. data/test/serializers/caching_configuration_test_isolated.rb +8 -6
  172. data/test/serializers/configuration_test.rb +2 -0
  173. data/test/serializers/fieldset_test.rb +3 -1
  174. data/test/serializers/meta_test.rb +14 -6
  175. data/test/serializers/options_test.rb +19 -6
  176. data/test/serializers/read_attribute_for_serialization_test.rb +5 -3
  177. data/test/serializers/reflection_test.rb +481 -0
  178. data/test/serializers/root_test.rb +3 -1
  179. data/test/serializers/serialization_test.rb +4 -2
  180. data/test/serializers/serializer_for_test.rb +14 -10
  181. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  182. data/test/support/isolated_unit.rb +11 -4
  183. data/test/support/rails5_shims.rb +10 -2
  184. data/test/support/rails_app.rb +4 -9
  185. data/test/support/serialization_testing.rb +33 -5
  186. data/test/test_helper.rb +15 -0
  187. metadata +126 -46
  188. data/.rubocop_todo.yml +0 -167
  189. data/docs/ARCHITECTURE.md +0 -126
  190. data/lib/active_model/serializer/associations.rb +0 -100
  191. data/lib/active_model/serializer/attributes.rb +0 -82
  192. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  193. data/lib/active_model/serializer/configuration.rb +0 -35
  194. data/lib/active_model/serializer/include_tree.rb +0 -111
  195. data/lib/active_model/serializer/links.rb +0 -35
  196. data/lib/active_model/serializer/meta.rb +0 -29
  197. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  198. data/lib/active_model/serializer/type.rb +0 -25
  199. data/lib/active_model_serializers/key_transform.rb +0 -70
  200. data/test/active_model_serializers/key_transform_test.rb +0 -263
  201. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  202. data/test/adapter/json_api/relationships_test.rb +0 -199
  203. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  204. data/test/include_tree/from_include_args_test.rb +0 -26
  205. data/test/include_tree/from_string_test.rb +0 -94
  206. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
  require 'will_paginate/array'
3
5
  require 'kaminari'
@@ -14,9 +16,9 @@ module ActionController
14
16
  class PaginationTestController < ActionController::Base
15
17
  def setup
16
18
  @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' })
19
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
20
+ Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
21
+ Profile.new(name: 'Name 3', description: 'Description 3', comments: 'Comments 3')
20
22
  ]
21
23
  end
22
24
 
@@ -48,20 +50,22 @@ module ActionController
48
50
 
49
51
  def test_render_pagination_links_with_will_paginate
50
52
  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" }
53
+ 'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
54
+ 'prev' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
55
+ 'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
56
+ 'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
55
57
 
56
58
  get :render_pagination_using_will_paginate, params: { page: { number: 2, size: 1 } }
57
59
  response = JSON.parse(@response.body)
58
60
  assert_equal expected_links, response['links']
59
61
  end
60
62
 
61
- def test_render_only_last_and_next_pagination_links
63
+ def test_render_only_first_last_and_next_pagination_links
62
64
  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
+ 'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
66
+ 'prev' => nil,
67
+ 'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
68
+ 'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2" }
65
69
  get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 } }
66
70
  response = JSON.parse(@response.body)
67
71
  assert_equal expected_links, response['links']
@@ -69,37 +73,43 @@ module ActionController
69
73
 
70
74
  def test_render_pagination_links_with_kaminari
71
75
  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
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
77
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
78
+ 'next' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1",
79
+ 'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
76
80
  get :render_pagination_using_kaminari, params: { page: { number: 2, size: 1 } }
77
81
  response = JSON.parse(@response.body)
78
82
  assert_equal expected_links, response['links']
79
83
  end
80
84
 
81
- def test_render_only_prev_and_first_pagination_links
85
+ def test_render_only_prev_first_and_last_pagination_links
82
86
  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" }
87
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1",
88
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1",
89
+ 'next' => nil,
90
+ 'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1" }
85
91
  get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
86
92
  response = JSON.parse(@response.body)
87
93
  assert_equal expected_links, response['links']
88
94
  end
89
95
 
90
- def test_render_only_last_and_next_pagination_links_with_additional_params
96
+ def test_render_only_first_last_and_next_pagination_links_with_additional_params
91
97
  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" }
98
+ 'first' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2&teste=additional",
99
+ 'prev' => nil,
100
+ 'next' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional",
101
+ 'last' => "#{WILL_PAGINATE_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2&teste=additional" }
94
102
  get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
95
103
  response = JSON.parse(@response.body)
96
104
  assert_equal expected_links, response['links']
97
105
  end
98
106
 
99
- def test_render_only_prev_and_first_pagination_links_with_additional_params
107
+ def test_render_only_prev_first_and_last_pagination_links_with_additional_params
100
108
  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" }
109
+ 'first' => "#{KAMINARI_URI}?page%5Bnumber%5D=1&page%5Bsize%5D=1&teste=additional",
110
+ 'prev' => "#{KAMINARI_URI}?page%5Bnumber%5D=2&page%5Bsize%5D=1&teste=additional",
111
+ 'next' => nil,
112
+ 'last' => "#{KAMINARI_URI}?page%5Bnumber%5D=3&page%5Bsize%5D=1&teste=additional" }
103
113
  get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
104
114
  response = JSON.parse(@response.body)
105
115
  assert_equal expected_links, response['links']
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActionController
@@ -5,7 +7,17 @@ module ActionController
5
7
  class JsonApi
6
8
  class KeyTransformTest < ActionController::TestCase
7
9
  class KeyTransformTestController < ActionController::Base
8
- Post = Class.new(::Model)
10
+ class Post < ::Model
11
+ attributes :title, :body, :publish_at
12
+ associations :author, :top_comments
13
+ end
14
+ class Author < ::Model
15
+ attributes :first_name, :last_name
16
+ end
17
+ class TopComment < ::Model
18
+ attributes :body
19
+ associations :author, :post
20
+ end
9
21
  class PostSerializer < ActiveModel::Serializer
10
22
  type 'posts'
11
23
  attributes :title, :body, :publish_at
@@ -22,13 +34,11 @@ module ActionController
22
34
  end
23
35
  end
24
36
 
25
- Author = Class.new(::Model)
26
37
  class AuthorSerializer < ActiveModel::Serializer
27
38
  type 'authors'
28
39
  attributes :first_name, :last_name
29
40
  end
30
41
 
31
- TopComment = Class.new(::Model)
32
42
  class TopCommentSerializer < ActiveModel::Serializer
33
43
  type 'top_comments'
34
44
  attributes :body
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActionController
6
+ module Serialization
7
+ class LookupProcTest < ActionController::TestCase
8
+ module Api
9
+ module V3
10
+ class PostCustomSerializer < ActiveModel::Serializer
11
+ attributes :title, :body
12
+
13
+ belongs_to :author
14
+ end
15
+
16
+ class AuthorCustomSerializer < ActiveModel::Serializer
17
+ attributes :name
18
+ end
19
+
20
+ class LookupProcTestController < ActionController::Base
21
+ def implicit_namespaced_serializer
22
+ author = Author.new(name: 'Bob')
23
+ post = Post.new(title: 'New Post', body: 'Body', author: author)
24
+
25
+ render json: post
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ tests Api::V3::LookupProcTestController
32
+
33
+ test 'implicitly uses namespaced serializer' do
34
+ controller_namespace = lambda do |resource_class, _parent_serializer_class, namespace|
35
+ "#{namespace}::#{resource_class}CustomSerializer" if namespace
36
+ end
37
+
38
+ with_prepended_lookup(controller_namespace) do
39
+ get :implicit_namespaced_serializer
40
+
41
+ assert_serializer Api::V3::PostCustomSerializer
42
+
43
+ expected = { 'title' => 'New Post', 'body' => 'Body', 'author' => { 'name' => 'Bob' } }
44
+ actual = JSON.parse(@response.body)
45
+
46
+ assert_equal expected, actual
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActionController
6
+ module Serialization
7
+ class NamespaceLookupTest < ActionController::TestCase
8
+ class Book < ::Model
9
+ attributes :id, :title, :body
10
+ associations :writer, :chapters
11
+ end
12
+ class Chapter < ::Model
13
+ attributes :title
14
+ end
15
+ class Writer < ::Model
16
+ attributes :name
17
+ end
18
+
19
+ module Api
20
+ module V2
21
+ class BookSerializer < ActiveModel::Serializer
22
+ attributes :title
23
+ end
24
+ end
25
+
26
+ module VHeader
27
+ class BookSerializer < ActiveModel::Serializer
28
+ attributes :title, :body
29
+
30
+ def body
31
+ 'header'
32
+ end
33
+ end
34
+ end
35
+
36
+ module V3
37
+ class BookSerializer < ActiveModel::Serializer
38
+ attributes :title, :body
39
+
40
+ belongs_to :writer
41
+ has_many :chapters
42
+ end
43
+
44
+ class ChapterSerializer < ActiveModel::Serializer
45
+ attribute :title do
46
+ "Chapter - #{object.title}"
47
+ end
48
+ end
49
+
50
+ class WriterSerializer < ActiveModel::Serializer
51
+ attributes :name
52
+ end
53
+
54
+ class LookupTestController < ActionController::Base
55
+ before_action only: [:namespace_set_in_before_filter] do
56
+ self.namespace_for_serializer = Api::V2
57
+ end
58
+
59
+ def implicit_namespaced_serializer
60
+ writer = Writer.new(name: 'Bob')
61
+ book = Book.new(title: 'New Post', body: 'Body', writer: writer, chapters: [])
62
+
63
+ render json: book
64
+ end
65
+
66
+ def implicit_namespaced_collection_serializer
67
+ chapter1 = Chapter.new(title: 'Oh')
68
+ chapter2 = Chapter.new(title: 'Oh my')
69
+
70
+ render json: [chapter1, chapter2]
71
+ end
72
+
73
+ def implicit_has_many_namespaced_serializer
74
+ chapter1 = Chapter.new(title: 'Odd World')
75
+ chapter2 = Chapter.new(title: 'New World')
76
+ book = Book.new(title: 'New Post', body: 'Body', chapters: [chapter1, chapter2])
77
+
78
+ render json: book
79
+ end
80
+
81
+ def explicit_namespace_as_module
82
+ book = Book.new(title: 'New Post', body: 'Body')
83
+
84
+ render json: book, namespace: Api::V2
85
+ end
86
+
87
+ def explicit_namespace_as_string
88
+ book = Book.new(title: 'New Post', body: 'Body')
89
+
90
+ # because this is a string, ruby can't auto-lookup the constant, so otherwise
91
+ # the lookup thinks we mean ::Api::V2
92
+ render json: book, namespace: 'ActionController::Serialization::NamespaceLookupTest::Api::V2'
93
+ end
94
+
95
+ def explicit_namespace_as_symbol
96
+ book = Book.new(title: 'New Post', body: 'Body')
97
+
98
+ # because this is a string, ruby can't auto-lookup the constant, so otherwise
99
+ # the lookup thinks we mean ::Api::V2
100
+ render json: book, namespace: :'ActionController::Serialization::NamespaceLookupTest::Api::V2'
101
+ end
102
+
103
+ def invalid_namespace
104
+ book = Book.new(id: 'invalid_namespace_book_id', title: 'New Post', body: 'Body')
105
+
106
+ render json: book, namespace: :api_v2
107
+ end
108
+
109
+ def namespace_set_in_before_filter
110
+ book = Book.new(title: 'New Post', body: 'Body')
111
+ render json: book
112
+ end
113
+
114
+ def namespace_set_by_request_headers
115
+ book = Book.new(title: 'New Post', body: 'Body')
116
+ version_from_header = request.headers['X-API_VERSION']
117
+ namespace = "ActionController::Serialization::NamespaceLookupTest::#{version_from_header}"
118
+
119
+ render json: book, namespace: namespace
120
+ end
121
+ end
122
+ end
123
+ end
124
+
125
+ tests Api::V3::LookupTestController
126
+
127
+ setup do
128
+ @test_namespace = self.class.parent
129
+ end
130
+
131
+ test 'uses request headers to determine the namespace' do
132
+ request.env['X-API_VERSION'] = 'Api::VHeader'
133
+ get :namespace_set_by_request_headers
134
+
135
+ assert_serializer Api::VHeader::BookSerializer
136
+ end
137
+
138
+ test 'implicitly uses namespaced serializer' do
139
+ get :implicit_namespaced_serializer
140
+
141
+ assert_serializer Api::V3::BookSerializer
142
+
143
+ expected = { 'title' => 'New Post', 'body' => 'Body', 'writer' => { 'name' => 'Bob' }, 'chapters' => [] }
144
+ actual = JSON.parse(@response.body)
145
+
146
+ assert_equal expected, actual
147
+ end
148
+
149
+ test 'implicitly uses namespaced serializer for collection' do
150
+ get :implicit_namespaced_collection_serializer
151
+
152
+ assert_serializer 'ActiveModel::Serializer::CollectionSerializer'
153
+
154
+ expected = [{ 'title' => 'Chapter - Oh' }, { 'title' => 'Chapter - Oh my' }]
155
+ actual = JSON.parse(@response.body)
156
+
157
+ assert_equal expected, actual
158
+ end
159
+
160
+ test 'implicitly uses namespaced serializer for has_many' do
161
+ get :implicit_has_many_namespaced_serializer
162
+
163
+ assert_serializer Api::V3::BookSerializer
164
+
165
+ expected = {
166
+ 'title' => 'New Post',
167
+ 'body' => 'Body', 'writer' => nil,
168
+ 'chapters' => [
169
+ { 'title' => 'Chapter - Odd World' },
170
+ { 'title' => 'Chapter - New World' }
171
+ ]
172
+ }
173
+ actual = JSON.parse(@response.body)
174
+
175
+ assert_equal expected, actual
176
+ end
177
+
178
+ test 'explicit namespace as module' do
179
+ get :explicit_namespace_as_module
180
+
181
+ assert_serializer Api::V2::BookSerializer
182
+
183
+ expected = { 'title' => 'New Post' }
184
+ actual = JSON.parse(@response.body)
185
+
186
+ assert_equal expected, actual
187
+ end
188
+
189
+ test 'explicit namespace as string' do
190
+ get :explicit_namespace_as_string
191
+
192
+ assert_serializer Api::V2::BookSerializer
193
+
194
+ expected = { 'title' => 'New Post' }
195
+ actual = JSON.parse(@response.body)
196
+
197
+ assert_equal expected, actual
198
+ end
199
+
200
+ test 'explicit namespace as symbol' do
201
+ get :explicit_namespace_as_symbol
202
+
203
+ assert_serializer Api::V2::BookSerializer
204
+
205
+ expected = { 'title' => 'New Post' }
206
+ actual = JSON.parse(@response.body)
207
+
208
+ assert_equal expected, actual
209
+ end
210
+
211
+ test 'invalid namespace' do
212
+ get :invalid_namespace
213
+
214
+ assert_serializer ActiveModel::Serializer::Null
215
+
216
+ expected = { 'id' => 'invalid_namespace_book_id', 'title' => 'New Post', 'body' => 'Body' }
217
+ actual = JSON.parse(@response.body)
218
+
219
+ assert_equal expected, actual
220
+ end
221
+
222
+ test 'namespace set in before filter' do
223
+ get :namespace_set_in_before_filter
224
+
225
+ assert_serializer Api::V2::BookSerializer
226
+
227
+ expected = { 'title' => 'New Post' }
228
+ actual = JSON.parse(@response.body)
229
+
230
+ assert_equal expected, actual
231
+ end
232
+ end
233
+ end
234
+ end
@@ -1,17 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module SerializationScopeTesting
4
6
  class User < ActiveModelSerializers::Model
5
- attr_accessor :id, :name, :admin
7
+ attributes :id, :name, :admin
6
8
  def admin?
7
9
  admin
8
10
  end
9
11
  end
10
12
  class Comment < ActiveModelSerializers::Model
11
- attr_accessor :id, :body
13
+ attributes :id, :body
12
14
  end
13
15
  class Post < ActiveModelSerializers::Model
14
- attr_accessor :id, :title, :body, :comments
16
+ attributes :id, :title, :body, :comments
15
17
  end
16
18
  class PostSerializer < ActiveModel::Serializer
17
19
  attributes :id, :title, :body, :comments
@@ -33,7 +35,8 @@ module SerializationScopeTesting
33
35
  end
34
36
  end
35
37
  class PostTestController < ActionController::Base
36
- attr_accessor :current_user
38
+ attr_writer :current_user
39
+
37
40
  def render_post_by_non_admin
38
41
  self.current_user = User.new(id: 3, name: 'Pete', admin: false)
39
42
  render json: new_post, serializer: serializer, adapter: :json
@@ -44,6 +47,10 @@ module SerializationScopeTesting
44
47
  render json: new_post, serializer: serializer, adapter: :json
45
48
  end
46
49
 
50
+ def current_user
51
+ defined?(@current_user) ? @current_user : :current_user_not_set
52
+ end
53
+
47
54
  private
48
55
 
49
56
  def new_post
@@ -75,7 +82,8 @@ module SerializationScopeTesting
75
82
  end
76
83
 
77
84
  def test_default_serialization_scope_object
78
- assert_equal @controller.current_user, @controller.serialization_scope
85
+ assert_equal :current_user_not_set, @controller.current_user
86
+ assert_equal :current_user_not_set, @controller.serialization_scope
79
87
  end
80
88
 
81
89
  def test_default_scope_non_admin
@@ -125,7 +133,7 @@ module SerializationScopeTesting
125
133
  end
126
134
 
127
135
  def test_defined_serialization_scope_object
128
- assert_equal @controller.view_context.class, @controller.serialization_scope.class
136
+ assert_equal @controller.view_context.controller, @controller.serialization_scope.controller
129
137
  end
130
138
 
131
139
  def test_serialization_scope_non_admin
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActionController
@@ -74,7 +76,7 @@ module ActionController
74
76
  end
75
77
 
76
78
  def update_and_render_object_with_cache_enabled
77
- @post.updated_at = Time.now
79
+ @post.updated_at = Time.zone.now
78
80
 
79
81
  generate_cached_serializer(@post)
80
82
  render json: @post
@@ -135,7 +137,7 @@ module ActionController
135
137
  like = Like.new(id: 1, likeable: comment, time: 3.days.ago)
136
138
 
137
139
  generate_cached_serializer(like)
138
- like.likable = comment2
140
+ like.likeable = comment2
139
141
  like.time = Time.zone.now.to_s
140
142
 
141
143
  render json: like
@@ -163,7 +165,7 @@ module ActionController
163
165
  end
164
166
  expected = {
165
167
  data: {
166
- id: assigns(:profile).id.to_s,
168
+ id: @controller.instance_variable_get(:@profile).id.to_s,
167
169
  type: 'profiles',
168
170
  attributes: {
169
171
  name: 'Name 1',
@@ -246,7 +248,7 @@ module ActionController
246
248
  expected = {
247
249
  data: [
248
250
  {
249
- id: assigns(:profiles).first.id.to_s,
251
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
250
252
  type: 'profiles',
251
253
  attributes: {
252
254
  name: 'Name 1',
@@ -269,7 +271,7 @@ module ActionController
269
271
  expected = {
270
272
  data: [
271
273
  {
272
- id: assigns(:profiles).first.id.to_s,
274
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
273
275
  type: 'profiles',
274
276
  attributes: {
275
277
  name: 'Name 1',
@@ -294,7 +296,8 @@ module ActionController
294
296
  comments: [
295
297
  {
296
298
  id: 1,
297
- body: 'ZOMG A COMMENT' }
299
+ body: 'ZOMG A COMMENT'
300
+ }
298
301
  ],
299
302
  blog: {
300
303
  id: 999,
@@ -333,7 +336,8 @@ module ActionController
333
336
  comments: [
334
337
  {
335
338
  id: 1,
336
- body: 'ZOMG A COMMENT' }
339
+ body: 'ZOMG A COMMENT'
340
+ }
337
341
  ],
338
342
  blog: {
339
343
  id: 999,
@@ -407,7 +411,8 @@ module ActionController
407
411
  comments: [
408
412
  {
409
413
  id: 1,
410
- body: 'ZOMG A COMMENT' }
414
+ body: 'ZOMG A COMMENT'
415
+ }
411
416
  ],
412
417
  blog: {
413
418
  id: 999,
@@ -453,14 +458,20 @@ module ActionController
453
458
  end
454
459
  end
455
460
 
456
- def test_render_event_is_emmited
457
- subscriber = ::ActiveSupport::Notifications.subscribe('render.active_model_serializers') do |name|
458
- @name = name
461
+ def test_render_event_is_emitted
462
+ subscriber = ::ActiveSupport::Notifications.subscribe('render.active_model_serializers') do |subscribed_event|
463
+ @subscribed_event = subscribed_event
459
464
  end
460
465
 
461
466
  get :render_using_implicit_serializer
462
467
 
463
- assert_equal 'render.active_model_serializers', @name
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
464
475
  ensure
465
476
  ActiveSupport::Notifications.unsubscribe(subscriber) if subscriber
466
477
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModelSerializers
@@ -1,20 +1,24 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
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
5
+ module ActiveModelSerializers
6
+ class JsonPointerTest < ActiveSupport::TestCase
7
+ def test_attribute_pointer
8
+ attribute_name = 'title'
9
+ pointer = ActiveModelSerializers::JsonPointer.new(:attribute, attribute_name)
10
+ assert_equal '/data/attributes/title', pointer
11
+ end
9
12
 
10
- def test_primary_data_pointer
11
- pointer = ActiveModelSerializers::JsonPointer.new(:primary_data)
12
- assert_equal '/data', pointer
13
- end
13
+ def test_primary_data_pointer
14
+ pointer = ActiveModelSerializers::JsonPointer.new(:primary_data)
15
+ assert_equal '/data', pointer
16
+ end
14
17
 
15
- def test_unkown_data_pointer
16
- assert_raises(TypeError) do
17
- ActiveModelSerializers::JsonPointer.new(:unknown)
18
+ def test_unknown_data_pointer
19
+ assert_raises(TypeError) do
20
+ ActiveModelSerializers::JsonPointer.new(:unknown)
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel