active_model_serializers 0.10.0 → 0.10.3

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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -4
  3. data/.travis.yml +9 -1
  4. data/CHANGELOG.md +81 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +5 -2
  7. data/README.md +24 -24
  8. data/Rakefile +3 -3
  9. data/active_model_serializers.gemspec +20 -24
  10. data/docs/ARCHITECTURE.md +6 -7
  11. data/docs/README.md +2 -0
  12. data/docs/general/adapters.md +4 -2
  13. data/docs/general/caching.md +7 -1
  14. data/docs/general/configuration_options.md +70 -1
  15. data/docs/general/deserialization.md +1 -1
  16. data/docs/general/fields.md +31 -0
  17. data/docs/general/rendering.md +42 -3
  18. data/docs/general/serializers.md +97 -8
  19. data/docs/howto/add_pagination_links.md +4 -5
  20. data/docs/howto/add_relationship_links.md +137 -0
  21. data/docs/howto/add_root_key.md +4 -0
  22. data/docs/howto/grape_integration.md +42 -0
  23. data/docs/howto/outside_controller_use.md +9 -2
  24. data/docs/howto/passing_arbitrary_options.md +2 -2
  25. data/docs/howto/test.md +2 -0
  26. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  27. data/docs/integrations/ember-and-json-api.md +64 -32
  28. data/docs/jsonapi/schema.md +1 -1
  29. data/lib/action_controller/serialization.rb +13 -3
  30. data/lib/active_model/serializer/adapter/base.rb +2 -0
  31. data/lib/active_model/serializer/array_serializer.rb +8 -5
  32. data/lib/active_model/serializer/association.rb +19 -4
  33. data/lib/active_model/serializer/belongs_to_reflection.rb +0 -3
  34. data/lib/active_model/serializer/collection_serializer.rb +35 -12
  35. data/lib/active_model/serializer/{associations.rb → concerns/associations.rb} +13 -11
  36. data/lib/active_model/serializer/{attributes.rb → concerns/attributes.rb} +0 -0
  37. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +72 -113
  38. data/lib/active_model/serializer/{configuration.rb → concerns/configuration.rb} +25 -1
  39. data/lib/active_model/serializer/{links.rb → concerns/links.rb} +0 -0
  40. data/lib/active_model/serializer/{meta.rb → concerns/meta.rb} +0 -0
  41. data/lib/active_model/serializer/{type.rb → concerns/type.rb} +0 -0
  42. data/lib/active_model/serializer/error_serializer.rb +11 -7
  43. data/lib/active_model/serializer/errors_serializer.rb +25 -20
  44. data/lib/active_model/serializer/has_many_reflection.rb +0 -3
  45. data/lib/active_model/serializer/has_one_reflection.rb +0 -3
  46. data/lib/active_model/serializer/lint.rb +134 -130
  47. data/lib/active_model/serializer/reflection.rb +37 -21
  48. data/lib/active_model/serializer/version.rb +1 -1
  49. data/lib/active_model/serializer.rb +76 -37
  50. data/lib/active_model_serializers/adapter/attributes.rb +3 -66
  51. data/lib/active_model_serializers/adapter/base.rb +38 -38
  52. data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
  53. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
  54. data/lib/active_model_serializers/adapter/json_api/relationship.rb +30 -19
  55. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +23 -9
  56. data/lib/active_model_serializers/adapter/json_api.rb +44 -43
  57. data/lib/active_model_serializers/adapter.rb +6 -0
  58. data/lib/active_model_serializers/deprecate.rb +1 -2
  59. data/lib/active_model_serializers/deserialization.rb +2 -0
  60. data/lib/active_model_serializers/key_transform.rb +4 -0
  61. data/lib/active_model_serializers/lookup_chain.rb +80 -0
  62. data/lib/active_model_serializers/model.rb +4 -2
  63. data/lib/active_model_serializers/railtie.rb +3 -1
  64. data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
  65. data/lib/active_model_serializers/serializable_resource.rb +6 -5
  66. data/lib/active_model_serializers/serialization_context.rb +10 -3
  67. data/lib/active_model_serializers.rb +7 -0
  68. data/lib/generators/rails/serializer_generator.rb +4 -4
  69. data/lib/grape/active_model_serializers.rb +7 -5
  70. data/lib/grape/formatters/active_model_serializers.rb +19 -2
  71. data/lib/grape/helpers/active_model_serializers.rb +1 -0
  72. data/test/action_controller/adapter_selector_test.rb +4 -4
  73. data/test/action_controller/explicit_serializer_test.rb +5 -4
  74. data/test/action_controller/json/include_test.rb +106 -27
  75. data/test/action_controller/json_api/errors_test.rb +6 -7
  76. data/test/action_controller/json_api/fields_test.rb +57 -0
  77. data/test/action_controller/json_api/linked_test.rb +29 -24
  78. data/test/action_controller/json_api/pagination_test.rb +19 -19
  79. data/test/action_controller/json_api/transform_test.rb +3 -3
  80. data/test/action_controller/lookup_proc_test.rb +49 -0
  81. data/test/action_controller/namespace_lookup_test.rb +226 -0
  82. data/test/action_controller/serialization_test.rb +10 -7
  83. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  84. data/test/active_model_serializers/key_transform_test.rb +286 -252
  85. data/test/active_model_serializers/model_test.rb +17 -4
  86. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +143 -0
  87. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  88. data/test/adapter/attributes_test.rb +43 -0
  89. data/test/adapter/json/collection_test.rb +14 -0
  90. data/test/adapter/json/transform_test.rb +15 -15
  91. data/test/adapter/json_api/collection_test.rb +4 -3
  92. data/test/adapter/json_api/errors_test.rb +17 -19
  93. data/test/adapter/json_api/fields_test.rb +4 -3
  94. data/test/adapter/json_api/has_many_test.rb +39 -18
  95. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +166 -0
  96. data/test/adapter/json_api/json_api_test.rb +5 -7
  97. data/test/adapter/json_api/linked_test.rb +33 -12
  98. data/test/adapter/json_api/links_test.rb +4 -2
  99. data/test/adapter/json_api/pagination_links_test.rb +35 -8
  100. data/test/adapter/json_api/relationship_test.rb +309 -73
  101. data/test/adapter/json_api/resource_identifier_test.rb +27 -2
  102. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  103. data/test/adapter/json_api/transform_test.rb +255 -253
  104. data/test/adapter/json_api/type_test.rb +1 -1
  105. data/test/adapter/json_test.rb +8 -7
  106. data/test/adapter/null_test.rb +1 -2
  107. data/test/adapter/polymorphic_test.rb +5 -5
  108. data/test/adapter_test.rb +1 -1
  109. data/test/benchmark/app.rb +1 -1
  110. data/test/benchmark/benchmarking_support.rb +1 -1
  111. data/test/benchmark/bm_active_record.rb +81 -0
  112. data/test/benchmark/bm_adapter.rb +38 -0
  113. data/test/benchmark/bm_caching.rb +16 -16
  114. data/test/benchmark/bm_lookup_chain.rb +83 -0
  115. data/test/benchmark/bm_transform.rb +16 -5
  116. data/test/benchmark/controllers.rb +16 -17
  117. data/test/benchmark/fixtures.rb +72 -72
  118. data/test/cache_test.rb +143 -49
  119. data/test/collection_serializer_test.rb +3 -3
  120. data/test/fixtures/poro.rb +52 -48
  121. data/test/generators/serializer_generator_test.rb +22 -5
  122. data/test/grape_test.rb +152 -56
  123. data/test/lint_test.rb +1 -1
  124. data/test/logger_test.rb +13 -11
  125. data/test/serializable_resource_test.rb +18 -22
  126. data/test/serializers/association_macros_test.rb +3 -2
  127. data/test/serializers/associations_test.rb +107 -32
  128. data/test/serializers/attribute_test.rb +2 -2
  129. data/test/serializers/attributes_test.rb +1 -1
  130. data/test/serializers/fieldset_test.rb +1 -1
  131. data/test/serializers/meta_test.rb +12 -6
  132. data/test/serializers/root_test.rb +1 -1
  133. data/test/serializers/serializer_for_test.rb +6 -4
  134. data/test/serializers/serializer_for_with_namespace_test.rb +87 -0
  135. data/test/support/isolated_unit.rb +5 -2
  136. data/test/support/rails5_shims.rb +8 -2
  137. data/test/support/rails_app.rb +0 -9
  138. data/test/support/serialization_testing.rb +23 -5
  139. data/test/test_helper.rb +1 -0
  140. metadata +85 -34
  141. data/.rubocop_todo.yml +0 -167
  142. data/lib/active_model/serializer/include_tree.rb +0 -111
  143. data/test/adapter/json_api/relationships_test.rb +0 -199
  144. data/test/include_tree/from_include_args_test.rb +0 -26
  145. data/test/include_tree/from_string_test.rb +0 -94
  146. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -3,9 +3,8 @@ require 'test_helper'
3
3
  module ActionController
4
4
  module Serialization
5
5
  class JsonApi
6
- class LinkedTest < ActionController::TestCase
6
+ class LinkedTest < ActionDispatch::IntegrationTest
7
7
  class LinkedTestController < ActionController::Base
8
- require 'active_model_serializers/register_jsonapi_renderer'
9
8
  def setup_post
10
9
  ActionController::Base.cache_store.clear
11
10
  @role1 = Role.new(id: 1, name: 'admin')
@@ -39,62 +38,68 @@ module ActionController
39
38
 
40
39
  def render_resource_without_include
41
40
  setup_post
42
- render jsonapi: @post
41
+ render json: @post
43
42
  end
44
43
 
45
44
  def render_resource_with_include
46
45
  setup_post
47
- render jsonapi: @post, include: [:author]
46
+ render json: @post, adapter: :json_api, include: [:author]
48
47
  end
49
48
 
50
49
  def render_resource_with_include_of_custom_key_by_original
51
50
  setup_post
52
- render jsonapi: @post, include: [:reviews], serializer: PostWithCustomKeysSerializer
51
+ render json: @post, adapter: :json_api, include: [:reviews], serializer: PostWithCustomKeysSerializer
53
52
  end
54
53
 
55
54
  def render_resource_with_nested_include
56
55
  setup_post
57
- render jsonapi: @post, include: [comments: [:author]]
56
+ render json: @post, adapter: :json_api, include: [comments: [:author]]
58
57
  end
59
58
 
60
59
  def render_resource_with_nested_has_many_include_wildcard
61
60
  setup_post
62
- render jsonapi: @post, include: 'author.*'
61
+ render json: @post, adapter: :json_api, include: 'author.*'
63
62
  end
64
63
 
65
64
  def render_resource_with_missing_nested_has_many_include
66
65
  setup_post
67
66
  @post.author = @author2 # author2 has no roles.
68
- render jsonapi: @post, include: [author: [:roles]]
67
+ render json: @post, adapter: :json_api, include: [author: [:roles]]
69
68
  end
70
69
 
71
70
  def render_collection_with_missing_nested_has_many_include
72
71
  setup_post
73
72
  @post.author = @author2
74
- render jsonapi: [@post, @post2], include: [author: [:roles]]
73
+ render json: [@post, @post2], adapter: :json_api, include: [author: [:roles]]
75
74
  end
76
75
 
77
76
  def render_collection_without_include
78
77
  setup_post
79
- render jsonapi: [@post]
78
+ render json: [@post], adapter: :json_api
80
79
  end
81
80
 
82
81
  def render_collection_with_include
83
82
  setup_post
84
- render jsonapi: [@post], include: 'author, comments'
83
+ render json: [@post], adapter: :json_api, include: 'author, comments'
85
84
  end
86
85
  end
87
86
 
88
- tests LinkedTestController
87
+ setup do
88
+ @routes = Rails.application.routes.draw do
89
+ ActiveSupport::Deprecation.silence do
90
+ match ':action', to: LinkedTestController, via: [:get, :post]
91
+ end
92
+ end
93
+ end
89
94
 
90
95
  def test_render_resource_without_include
91
- get :render_resource_without_include
96
+ get '/render_resource_without_include'
92
97
  response = JSON.parse(@response.body)
93
98
  refute response.key? 'included'
94
99
  end
95
100
 
96
101
  def test_render_resource_with_include
97
- get :render_resource_with_include
102
+ get '/render_resource_with_include'
98
103
  response = JSON.parse(@response.body)
99
104
  assert response.key? 'included'
100
105
  assert_equal 1, response['included'].size
@@ -102,7 +107,7 @@ module ActionController
102
107
  end
103
108
 
104
109
  def test_render_resource_with_nested_has_many_include
105
- get :render_resource_with_nested_has_many_include_wildcard
110
+ get '/render_resource_with_nested_has_many_include_wildcard'
106
111
  response = JSON.parse(@response.body)
107
112
  expected_linked = [
108
113
  {
@@ -144,7 +149,7 @@ module ActionController
144
149
  end
145
150
 
146
151
  def test_render_resource_with_include_of_custom_key_by_original
147
- get :render_resource_with_include_of_custom_key_by_original
152
+ get '/render_resource_with_include_of_custom_key_by_original'
148
153
  response = JSON.parse(@response.body)
149
154
  assert response.key? 'included'
150
155
 
@@ -156,39 +161,39 @@ module ActionController
156
161
  end
157
162
 
158
163
  def test_render_resource_with_nested_include
159
- get :render_resource_with_nested_include
164
+ get '/render_resource_with_nested_include'
160
165
  response = JSON.parse(@response.body)
161
166
  assert response.key? 'included'
162
167
  assert_equal 3, response['included'].size
163
168
  end
164
169
 
165
170
  def test_render_collection_without_include
166
- get :render_collection_without_include
171
+ get '/render_collection_without_include'
167
172
  response = JSON.parse(@response.body)
168
173
  refute response.key? 'included'
169
174
  end
170
175
 
171
176
  def test_render_collection_with_include
172
- get :render_collection_with_include
177
+ get '/render_collection_with_include'
173
178
  response = JSON.parse(@response.body)
174
179
  assert response.key? 'included'
175
180
  end
176
181
 
177
182
  def test_render_resource_with_nested_attributes_even_when_missing_associations
178
- get :render_resource_with_missing_nested_has_many_include
183
+ get '/render_resource_with_missing_nested_has_many_include'
179
184
  response = JSON.parse(@response.body)
180
185
  assert response.key? 'included'
181
- refute has_type?(response['included'], 'roles')
186
+ refute include_type?(response['included'], 'roles')
182
187
  end
183
188
 
184
189
  def test_render_collection_with_missing_nested_has_many_include
185
- get :render_collection_with_missing_nested_has_many_include
190
+ get '/render_collection_with_missing_nested_has_many_include'
186
191
  response = JSON.parse(@response.body)
187
192
  assert response.key? 'included'
188
- assert has_type?(response['included'], 'roles')
193
+ assert include_type?(response['included'], 'roles')
189
194
  end
190
195
 
191
- def has_type?(collection, value)
196
+ def include_type?(collection, value)
192
197
  collection.detect { |i| i['type'] == value }
193
198
  end
194
199
  end
@@ -14,9 +14,9 @@ module ActionController
14
14
  class PaginationTestController < ActionController::Base
15
15
  def setup
16
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' })
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
20
  ]
21
21
  end
22
22
 
@@ -48,10 +48,10 @@ module ActionController
48
48
 
49
49
  def test_render_pagination_links_with_will_paginate
50
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" }
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
55
 
56
56
  get :render_pagination_using_will_paginate, params: { page: { number: 2, size: 1 } }
57
57
  response = JSON.parse(@response.body)
@@ -60,8 +60,8 @@ module ActionController
60
60
 
61
61
  def test_render_only_last_and_next_pagination_links
62
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" }
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
65
  get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 } }
66
66
  response = JSON.parse(@response.body)
67
67
  assert_equal expected_links, response['links']
@@ -69,10 +69,10 @@ module ActionController
69
69
 
70
70
  def test_render_pagination_links_with_kaminari
71
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" }
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
76
  get :render_pagination_using_kaminari, params: { page: { number: 2, size: 1 } }
77
77
  response = JSON.parse(@response.body)
78
78
  assert_equal expected_links, response['links']
@@ -80,8 +80,8 @@ module ActionController
80
80
 
81
81
  def test_render_only_prev_and_first_pagination_links
82
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" }
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
85
  get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 } }
86
86
  response = JSON.parse(@response.body)
87
87
  assert_equal expected_links, response['links']
@@ -89,8 +89,8 @@ module ActionController
89
89
 
90
90
  def test_render_only_last_and_next_pagination_links_with_additional_params
91
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" }
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
94
  get :render_pagination_using_will_paginate, params: { page: { number: 1, size: 2 }, teste: 'additional' }
95
95
  response = JSON.parse(@response.body)
96
96
  assert_equal expected_links, response['links']
@@ -98,8 +98,8 @@ module ActionController
98
98
 
99
99
  def test_render_only_prev_and_first_pagination_links_with_additional_params
100
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" }
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
103
  get :render_pagination_using_kaminari, params: { page: { number: 3, size: 1 }, teste: 'additional' }
104
104
  response = JSON.parse(@response.body)
105
105
  assert_equal expected_links, response['links']
@@ -5,7 +5,9 @@ module ActionController
5
5
  class JsonApi
6
6
  class KeyTransformTest < ActionController::TestCase
7
7
  class KeyTransformTestController < ActionController::Base
8
- Post = Class.new(::Model)
8
+ class Post < ::Model; end
9
+ class Author < ::Model; end
10
+ class TopComment < ::Model; end
9
11
  class PostSerializer < ActiveModel::Serializer
10
12
  type 'posts'
11
13
  attributes :title, :body, :publish_at
@@ -22,13 +24,11 @@ module ActionController
22
24
  end
23
25
  end
24
26
 
25
- Author = Class.new(::Model)
26
27
  class AuthorSerializer < ActiveModel::Serializer
27
28
  type 'authors'
28
29
  attributes :first_name, :last_name
29
30
  end
30
31
 
31
- TopComment = Class.new(::Model)
32
32
  class TopCommentSerializer < ActiveModel::Serializer
33
33
  type 'top_comments'
34
34
  attributes :body
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class LookupProcTest < ActionController::TestCase
6
+ module Api
7
+ module V3
8
+ class PostCustomSerializer < ActiveModel::Serializer
9
+ attributes :title, :body
10
+
11
+ belongs_to :author
12
+ end
13
+
14
+ class AuthorCustomSerializer < ActiveModel::Serializer
15
+ attributes :name
16
+ end
17
+
18
+ class LookupProcTestController < ActionController::Base
19
+ def implicit_namespaced_serializer
20
+ author = Author.new(name: 'Bob')
21
+ post = Post.new(title: 'New Post', body: 'Body', author: author)
22
+
23
+ render json: post
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ tests Api::V3::LookupProcTestController
30
+
31
+ test 'implicitly uses namespaced serializer' do
32
+ controller_namespace = lambda do |resource_class, _parent_serializer_class, namespace|
33
+ "#{namespace}::#{resource_class}CustomSerializer" if namespace
34
+ end
35
+
36
+ with_prepended_lookup(controller_namespace) do
37
+ get :implicit_namespaced_serializer
38
+
39
+ assert_serializer Api::V3::PostCustomSerializer
40
+
41
+ expected = { 'title' => 'New Post', 'body' => 'Body', 'author' => { 'name' => 'Bob' } }
42
+ actual = JSON.parse(@response.body)
43
+
44
+ assert_equal expected, actual
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,226 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class NamespaceLookupTest < ActionController::TestCase
6
+ class Book < ::Model; end
7
+ class Page < ::Model; end
8
+ class Chapter < ::Model; end
9
+ class Writer < ::Model; end
10
+
11
+ module Api
12
+ module V2
13
+ class BookSerializer < ActiveModel::Serializer
14
+ attributes :title
15
+ end
16
+ end
17
+
18
+ module VHeader
19
+ class BookSerializer < ActiveModel::Serializer
20
+ attributes :title, :body
21
+
22
+ def body
23
+ 'header'
24
+ end
25
+ end
26
+ end
27
+
28
+ module V3
29
+ class BookSerializer < ActiveModel::Serializer
30
+ attributes :title, :body
31
+
32
+ belongs_to :writer
33
+ has_many :chapters
34
+ end
35
+
36
+ class ChapterSerializer < ActiveModel::Serializer
37
+ attribute :title do
38
+ "Chapter - #{object.title}"
39
+ end
40
+ end
41
+
42
+ class WriterSerializer < ActiveModel::Serializer
43
+ attributes :name
44
+ end
45
+
46
+ class LookupTestController < ActionController::Base
47
+ before_action only: [:namespace_set_in_before_filter] do
48
+ self.namespace_for_serializer = Api::V2
49
+ end
50
+
51
+ def implicit_namespaced_serializer
52
+ writer = Writer.new(name: 'Bob')
53
+ book = Book.new(title: 'New Post', body: 'Body', writer: writer, chapters: [])
54
+
55
+ render json: book
56
+ end
57
+
58
+ def implicit_namespaced_collection_serializer
59
+ chapter1 = Chapter.new(title: 'Oh')
60
+ chapter2 = Chapter.new(title: 'Oh my')
61
+
62
+ render json: [chapter1, chapter2]
63
+ end
64
+
65
+ def implicit_has_many_namespaced_serializer
66
+ chapter1 = Chapter.new(title: 'Odd World')
67
+ chapter2 = Chapter.new(title: 'New World')
68
+ book = Book.new(title: 'New Post', body: 'Body', chapters: [chapter1, chapter2])
69
+
70
+ render json: book
71
+ end
72
+
73
+ def explicit_namespace_as_module
74
+ book = Book.new(title: 'New Post', body: 'Body')
75
+
76
+ render json: book, namespace: Api::V2
77
+ end
78
+
79
+ def explicit_namespace_as_string
80
+ book = Book.new(title: 'New Post', body: 'Body')
81
+
82
+ # because this is a string, ruby can't auto-lookup the constant, so otherwise
83
+ # the looku things we mean ::Api::V2
84
+ render json: book, namespace: 'ActionController::Serialization::NamespaceLookupTest::Api::V2'
85
+ end
86
+
87
+ def explicit_namespace_as_symbol
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 looku things we mean ::Api::V2
92
+ render json: book, namespace: :'ActionController::Serialization::NamespaceLookupTest::Api::V2'
93
+ end
94
+
95
+ def invalid_namespace
96
+ book = Book.new(title: 'New Post', body: 'Body')
97
+
98
+ render json: book, namespace: :api_v2
99
+ end
100
+
101
+ def namespace_set_in_before_filter
102
+ book = Book.new(title: 'New Post', body: 'Body')
103
+ render json: book
104
+ end
105
+
106
+ def namespace_set_by_request_headers
107
+ book = Book.new(title: 'New Post', body: 'Body')
108
+ version_from_header = request.headers['X-API_VERSION']
109
+ namespace = "ActionController::Serialization::NamespaceLookupTest::#{version_from_header}"
110
+
111
+ render json: book, namespace: namespace
112
+ end
113
+ end
114
+ end
115
+ end
116
+
117
+ tests Api::V3::LookupTestController
118
+
119
+ setup do
120
+ @test_namespace = self.class.parent
121
+ end
122
+
123
+ test 'uses request headers to determine the namespace' do
124
+ request.env['X-API_VERSION'] = 'Api::VHeader'
125
+ get :namespace_set_by_request_headers
126
+
127
+ assert_serializer Api::VHeader::BookSerializer
128
+ end
129
+
130
+ test 'implicitly uses namespaced serializer' do
131
+ get :implicit_namespaced_serializer
132
+
133
+ assert_serializer Api::V3::BookSerializer
134
+
135
+ expected = { 'title' => 'New Post', 'body' => 'Body', 'writer' => { 'name' => 'Bob' }, 'chapters' => [] }
136
+ actual = JSON.parse(@response.body)
137
+
138
+ assert_equal expected, actual
139
+ end
140
+
141
+ test 'implicitly uses namespaced serializer for collection' do
142
+ get :implicit_namespaced_collection_serializer
143
+
144
+ assert_serializer 'ActiveModel::Serializer::CollectionSerializer'
145
+
146
+ expected = [{ 'title' => 'Chapter - Oh' }, { 'title' => 'Chapter - Oh my' }]
147
+ actual = JSON.parse(@response.body)
148
+
149
+ assert_equal expected, actual
150
+ end
151
+
152
+ test 'implicitly uses namespaced serializer for has_many' do
153
+ get :implicit_has_many_namespaced_serializer
154
+
155
+ assert_serializer Api::V3::BookSerializer
156
+
157
+ expected = {
158
+ 'title' => 'New Post',
159
+ 'body' => 'Body', 'writer' => nil,
160
+ 'chapters' => [
161
+ { 'title' => 'Chapter - Odd World' },
162
+ { 'title' => 'Chapter - New World' }
163
+ ]
164
+ }
165
+ actual = JSON.parse(@response.body)
166
+
167
+ assert_equal expected, actual
168
+ end
169
+
170
+ test 'explicit namespace as module' do
171
+ get :explicit_namespace_as_module
172
+
173
+ assert_serializer Api::V2::BookSerializer
174
+
175
+ expected = { 'title' => 'New Post' }
176
+ actual = JSON.parse(@response.body)
177
+
178
+ assert_equal expected, actual
179
+ end
180
+
181
+ test 'explicit namespace as string' do
182
+ get :explicit_namespace_as_string
183
+
184
+ assert_serializer Api::V2::BookSerializer
185
+
186
+ expected = { 'title' => 'New Post' }
187
+ actual = JSON.parse(@response.body)
188
+
189
+ assert_equal expected, actual
190
+ end
191
+
192
+ test 'explicit namespace as symbol' do
193
+ get :explicit_namespace_as_symbol
194
+
195
+ assert_serializer Api::V2::BookSerializer
196
+
197
+ expected = { 'title' => 'New Post' }
198
+ actual = JSON.parse(@response.body)
199
+
200
+ assert_equal expected, actual
201
+ end
202
+
203
+ test 'invalid namespace' do
204
+ get :invalid_namespace
205
+
206
+ assert_serializer ActiveModel::Serializer::Null
207
+
208
+ expected = { 'title' => 'New Post', 'body' => 'Body' }
209
+ actual = JSON.parse(@response.body)
210
+
211
+ assert_equal expected, actual
212
+ end
213
+
214
+ test 'namespace set in before filter' do
215
+ get :namespace_set_in_before_filter
216
+
217
+ assert_serializer Api::V2::BookSerializer
218
+
219
+ expected = { 'title' => 'New Post' }
220
+ actual = JSON.parse(@response.body)
221
+
222
+ assert_equal expected, actual
223
+ end
224
+ end
225
+ end
226
+ end
@@ -74,7 +74,7 @@ module ActionController
74
74
  end
75
75
 
76
76
  def update_and_render_object_with_cache_enabled
77
- @post.updated_at = Time.now
77
+ @post.updated_at = Time.zone.now
78
78
 
79
79
  generate_cached_serializer(@post)
80
80
  render json: @post
@@ -163,7 +163,7 @@ module ActionController
163
163
  end
164
164
  expected = {
165
165
  data: {
166
- id: assigns(:profile).id.to_s,
166
+ id: @controller.instance_variable_get(:@profile).id.to_s,
167
167
  type: 'profiles',
168
168
  attributes: {
169
169
  name: 'Name 1',
@@ -246,7 +246,7 @@ module ActionController
246
246
  expected = {
247
247
  data: [
248
248
  {
249
- id: assigns(:profiles).first.id.to_s,
249
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
250
250
  type: 'profiles',
251
251
  attributes: {
252
252
  name: 'Name 1',
@@ -269,7 +269,7 @@ module ActionController
269
269
  expected = {
270
270
  data: [
271
271
  {
272
- id: assigns(:profiles).first.id.to_s,
272
+ id: @controller.instance_variable_get(:@profiles).first.id.to_s,
273
273
  type: 'profiles',
274
274
  attributes: {
275
275
  name: 'Name 1',
@@ -294,7 +294,8 @@ module ActionController
294
294
  comments: [
295
295
  {
296
296
  id: 1,
297
- body: 'ZOMG A COMMENT' }
297
+ body: 'ZOMG A COMMENT'
298
+ }
298
299
  ],
299
300
  blog: {
300
301
  id: 999,
@@ -333,7 +334,8 @@ module ActionController
333
334
  comments: [
334
335
  {
335
336
  id: 1,
336
- body: 'ZOMG A COMMENT' }
337
+ body: 'ZOMG A COMMENT'
338
+ }
337
339
  ],
338
340
  blog: {
339
341
  id: 999,
@@ -407,7 +409,8 @@ module ActionController
407
409
  comments: [
408
410
  {
409
411
  id: 1,
410
- body: 'ZOMG A COMMENT' }
412
+ body: 'ZOMG A COMMENT'
413
+ }
411
414
  ],
412
415
  blog: {
413
416
  id: 999,
@@ -1,20 +1,22 @@
1
1
  require 'test_helper'
2
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
3
+ module ActiveModelSerializers
4
+ class JsonPointerTest < ActiveSupport::TestCase
5
+ def test_attribute_pointer
6
+ attribute_name = 'title'
7
+ pointer = ActiveModelSerializers::JsonPointer.new(:attribute, attribute_name)
8
+ assert_equal '/data/attributes/title', pointer
9
+ end
9
10
 
10
- def test_primary_data_pointer
11
- pointer = ActiveModelSerializers::JsonPointer.new(:primary_data)
12
- assert_equal '/data', pointer
13
- end
11
+ def test_primary_data_pointer
12
+ pointer = ActiveModelSerializers::JsonPointer.new(:primary_data)
13
+ assert_equal '/data', pointer
14
+ end
14
15
 
15
- def test_unkown_data_pointer
16
- assert_raises(TypeError) do
17
- ActiveModelSerializers::JsonPointer.new(:unknown)
16
+ def test_unkown_data_pointer
17
+ assert_raises(TypeError) do
18
+ ActiveModelSerializers::JsonPointer.new(:unknown)
19
+ end
18
20
  end
19
21
  end
20
22
  end