active_model_serializers 0.8.3 → 0.10.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -0
  3. data/.rubocop.yml +86 -0
  4. data/.rubocop_todo.yml +240 -0
  5. data/.simplecov +111 -0
  6. data/.travis.yml +33 -22
  7. data/CHANGELOG.md +358 -6
  8. data/CONTRIBUTING.md +220 -0
  9. data/Gemfile +46 -1
  10. data/{MIT-LICENSE.txt → LICENSE.txt} +3 -2
  11. data/README.md +81 -591
  12. data/Rakefile +68 -11
  13. data/active_model_serializers.gemspec +57 -23
  14. data/appveyor.yml +27 -0
  15. data/docs/ARCHITECTURE.md +120 -0
  16. data/docs/DESIGN.textile +8 -0
  17. data/docs/README.md +35 -0
  18. data/docs/general/adapters.md +162 -0
  19. data/docs/general/caching.md +52 -0
  20. data/docs/general/configuration_options.md +27 -0
  21. data/docs/general/getting_started.md +98 -0
  22. data/docs/general/instrumentation.md +40 -0
  23. data/docs/general/logging.md +14 -0
  24. data/docs/general/rendering.md +153 -0
  25. data/docs/general/serializers.md +207 -0
  26. data/docs/how-open-source-maintained.jpg +0 -0
  27. data/docs/howto/add_pagination_links.md +121 -0
  28. data/docs/howto/add_root_key.md +51 -0
  29. data/docs/howto/outside_controller_use.md +58 -0
  30. data/docs/howto/test.md +152 -0
  31. data/docs/integrations/ember-and-json-api.md +112 -0
  32. data/docs/integrations/grape.md +19 -0
  33. data/docs/jsonapi/schema/schema.json +366 -0
  34. data/docs/jsonapi/schema.md +140 -0
  35. data/lib/action_controller/serialization.rb +41 -37
  36. data/lib/active_model/serializable_resource.rb +72 -0
  37. data/lib/active_model/serializer/adapter/attributes.rb +66 -0
  38. data/lib/active_model/serializer/adapter/base.rb +58 -0
  39. data/lib/active_model/serializer/adapter/cached_serializer.rb +45 -0
  40. data/lib/active_model/serializer/adapter/fragment_cache.rb +111 -0
  41. data/lib/active_model/serializer/adapter/json/fragment_cache.rb +13 -0
  42. data/lib/active_model/serializer/adapter/json.rb +21 -0
  43. data/lib/active_model/serializer/adapter/json_api/deserialization.rb +207 -0
  44. data/lib/active_model/serializer/adapter/json_api/fragment_cache.rb +21 -0
  45. data/lib/active_model/serializer/adapter/json_api/link.rb +44 -0
  46. data/lib/active_model/serializer/adapter/json_api/pagination_links.rb +58 -0
  47. data/lib/active_model/serializer/adapter/json_api.rb +223 -0
  48. data/lib/active_model/serializer/adapter/null.rb +11 -0
  49. data/lib/active_model/serializer/adapter.rb +91 -0
  50. data/lib/active_model/serializer/array_serializer.rb +9 -0
  51. data/lib/active_model/serializer/association.rb +20 -0
  52. data/lib/active_model/serializer/associations.rb +87 -220
  53. data/lib/active_model/serializer/attribute.rb +25 -0
  54. data/lib/active_model/serializer/attributes.rb +82 -0
  55. data/lib/active_model/serializer/belongs_to_reflection.rb +10 -0
  56. data/lib/active_model/serializer/caching.rb +100 -0
  57. data/lib/active_model/serializer/collection_reflection.rb +7 -0
  58. data/lib/active_model/serializer/collection_serializer.rb +47 -0
  59. data/lib/active_model/serializer/configuration.rb +28 -0
  60. data/lib/active_model/serializer/field.rb +56 -0
  61. data/lib/active_model/serializer/fieldset.rb +31 -0
  62. data/lib/active_model/serializer/has_many_reflection.rb +10 -0
  63. data/lib/active_model/serializer/has_one_reflection.rb +10 -0
  64. data/lib/active_model/serializer/include_tree.rb +111 -0
  65. data/lib/active_model/serializer/links.rb +33 -0
  66. data/lib/active_model/serializer/lint.rb +142 -0
  67. data/lib/active_model/serializer/reflection.rb +91 -0
  68. data/lib/active_model/serializer/singular_reflection.rb +7 -0
  69. data/lib/active_model/serializer/type.rb +25 -0
  70. data/lib/active_model/{serializers → serializer}/version.rb +1 -1
  71. data/lib/active_model/serializer.rb +99 -479
  72. data/lib/active_model_serializers/callbacks.rb +55 -0
  73. data/lib/active_model_serializers/deserialization.rb +13 -0
  74. data/lib/active_model_serializers/logging.rb +119 -0
  75. data/lib/active_model_serializers/model.rb +39 -0
  76. data/lib/active_model_serializers/railtie.rb +38 -0
  77. data/lib/active_model_serializers/serialization_context.rb +10 -0
  78. data/lib/active_model_serializers/test/schema.rb +103 -0
  79. data/lib/active_model_serializers/test/serializer.rb +125 -0
  80. data/lib/active_model_serializers/test.rb +7 -0
  81. data/lib/active_model_serializers.rb +20 -92
  82. data/lib/generators/rails/USAGE +6 -0
  83. data/lib/generators/rails/resource_override.rb +10 -0
  84. data/lib/generators/rails/serializer_generator.rb +36 -0
  85. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  86. data/lib/grape/active_model_serializers.rb +14 -0
  87. data/lib/grape/formatters/active_model_serializers.rb +15 -0
  88. data/lib/grape/helpers/active_model_serializers.rb +16 -0
  89. data/test/action_controller/adapter_selector_test.rb +53 -0
  90. data/test/action_controller/explicit_serializer_test.rb +134 -0
  91. data/test/action_controller/json/include_test.rb +167 -0
  92. data/test/action_controller/json_api/deserialization_test.rb +59 -0
  93. data/test/action_controller/json_api/linked_test.rb +196 -0
  94. data/test/action_controller/json_api/pagination_test.rb +116 -0
  95. data/test/{serialization_scope_name_test.rb → action_controller/serialization_scope_name_test.rb} +11 -15
  96. data/test/action_controller/serialization_test.rb +435 -0
  97. data/test/active_model_serializers/logging_test.rb +77 -0
  98. data/test/active_model_serializers/model_test.rb +9 -0
  99. data/test/active_model_serializers/railtie_test_isolated.rb +57 -0
  100. data/test/active_model_serializers/serialization_context_test.rb +18 -0
  101. data/test/active_model_serializers/test/schema_test.rb +128 -0
  102. data/test/active_model_serializers/test/serializer_test.rb +63 -0
  103. data/test/active_record_test.rb +9 -0
  104. data/test/adapter/fragment_cache_test.rb +38 -0
  105. data/test/adapter/json/belongs_to_test.rb +47 -0
  106. data/test/adapter/json/collection_test.rb +92 -0
  107. data/test/adapter/json/has_many_test.rb +47 -0
  108. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  109. data/test/adapter/json_api/collection_test.rb +97 -0
  110. data/test/adapter/json_api/fields_test.rb +89 -0
  111. data/test/adapter/json_api/has_many_embed_ids_test.rb +45 -0
  112. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  113. data/test/adapter/json_api/has_many_test.rb +145 -0
  114. data/test/adapter/json_api/has_one_test.rb +81 -0
  115. data/test/adapter/json_api/json_api_test.rb +37 -0
  116. data/test/adapter/json_api/linked_test.rb +394 -0
  117. data/test/adapter/json_api/links_test.rb +68 -0
  118. data/test/adapter/json_api/pagination_links_test.rb +115 -0
  119. data/test/adapter/json_api/parse_test.rb +139 -0
  120. data/test/adapter/json_api/resource_type_config_test.rb +71 -0
  121. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  122. data/test/adapter/json_test.rb +47 -0
  123. data/test/adapter/null_test.rb +25 -0
  124. data/test/adapter_test.rb +42 -0
  125. data/test/array_serializer_test.rb +36 -73
  126. data/test/collection_serializer_test.rb +100 -0
  127. data/test/fixtures/active_record.rb +56 -0
  128. data/test/fixtures/poro.rb +229 -0
  129. data/test/generators/scaffold_controller_generator_test.rb +24 -0
  130. data/test/generators/serializer_generator_test.rb +57 -0
  131. data/test/grape_test.rb +82 -0
  132. data/test/include_tree/from_include_args_test.rb +26 -0
  133. data/test/include_tree/from_string_test.rb +94 -0
  134. data/test/include_tree/include_args_to_hash_test.rb +64 -0
  135. data/test/lint_test.rb +40 -0
  136. data/test/logger_test.rb +18 -0
  137. data/test/poro_test.rb +9 -0
  138. data/test/serializable_resource_test.rb +27 -0
  139. data/test/serializers/adapter_for_test.rb +166 -0
  140. data/test/serializers/association_macros_test.rb +36 -0
  141. data/test/serializers/associations_test.rb +267 -0
  142. data/test/serializers/attribute_test.rb +123 -0
  143. data/test/serializers/attributes_test.rb +52 -0
  144. data/test/serializers/cache_test.rb +209 -0
  145. data/test/serializers/configuration_test.rb +32 -0
  146. data/test/serializers/fieldset_test.rb +14 -0
  147. data/test/serializers/meta_test.rb +130 -0
  148. data/test/serializers/options_test.rb +21 -0
  149. data/test/serializers/root_test.rb +21 -0
  150. data/test/serializers/serializer_for_test.rb +134 -0
  151. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  152. data/test/support/isolated_unit.rb +77 -0
  153. data/test/support/rails5_shims.rb +29 -0
  154. data/test/support/rails_app.rb +25 -0
  155. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  156. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  157. data/test/support/schemas/custom/show.json +7 -0
  158. data/test/support/schemas/hyper_schema.json +93 -0
  159. data/test/support/schemas/render_using_json_api.json +43 -0
  160. data/test/support/schemas/simple_json_pointers.json +10 -0
  161. data/test/support/serialization_testing.rb +53 -0
  162. data/test/support/simplecov.rb +6 -0
  163. data/test/support/stream_capture.rb +50 -0
  164. data/test/support/test_case.rb +19 -0
  165. data/test/test_helper.rb +55 -24
  166. metadata +358 -42
  167. data/DESIGN.textile +0 -586
  168. data/Gemfile.edge +0 -9
  169. data/bench/perf.rb +0 -43
  170. data/cruft.md +0 -19
  171. data/lib/active_model/array_serializer.rb +0 -104
  172. data/lib/active_record/serializer_override.rb +0 -16
  173. data/lib/generators/resource_override.rb +0 -13
  174. data/lib/generators/serializer/USAGE +0 -9
  175. data/lib/generators/serializer/serializer_generator.rb +0 -42
  176. data/lib/generators/serializer/templates/serializer.rb +0 -19
  177. data/test/association_test.rb +0 -592
  178. data/test/caching_test.rb +0 -96
  179. data/test/generators_test.rb +0 -85
  180. data/test/no_serialization_scope_test.rb +0 -34
  181. data/test/serialization_test.rb +0 -392
  182. data/test/serializer_support_test.rb +0 -51
  183. data/test/serializer_test.rb +0 -1465
  184. 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'
12
+ WILL_PAGINATE_URI = 'http://test.host/action_controller/serialization/json_api/pagination_test/pagination_test/render_pagination_using_will_paginate'
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
@@ -2,59 +2,55 @@ require 'test_helper'
2
2
  require 'pathname'
3
3
 
4
4
  class DefaultScopeNameTest < ActionController::TestCase
5
- TestUser = Struct.new(:name, :admin)
6
-
7
5
  class UserSerializer < ActiveModel::Serializer
8
- attributes :admin?
9
6
  def admin?
10
7
  current_user.admin
11
8
  end
9
+ attributes :admin?
12
10
  end
13
11
 
14
12
  class UserTestController < ActionController::Base
15
13
  protect_from_forgery
16
14
 
17
- before_filter { request.format = :json }
15
+ before_action { request.format = :json }
18
16
 
19
17
  def current_user
20
- TestUser.new('Pete', false)
18
+ User.new(id: 1, name: 'Pete', admin: false)
21
19
  end
22
20
 
23
21
  def render_new_user
24
- render :json => TestUser.new('pete', false), :serializer => UserSerializer
22
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: UserSerializer, adapter: :json_api
25
23
  end
26
24
  end
27
25
 
28
- tests UserTestController
26
+ tests UserTestController
29
27
 
30
28
  def test_default_scope_name
31
29
  get :render_new_user
32
- assert_equal '{"user":{"admin":false}}', @response.body
30
+ assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":false}}}', @response.body
33
31
  end
34
32
  end
35
33
 
36
34
  class SerializationScopeNameTest < ActionController::TestCase
37
- TestUser = Struct.new(:name, :admin)
38
-
39
35
  class AdminUserSerializer < ActiveModel::Serializer
40
- attributes :admin?
41
36
  def admin?
42
37
  current_admin.admin
43
38
  end
39
+ attributes :admin?
44
40
  end
45
41
 
46
42
  class AdminUserTestController < ActionController::Base
47
43
  protect_from_forgery
48
44
 
49
45
  serialization_scope :current_admin
50
- before_filter { request.format = :json }
46
+ before_action { request.format = :json }
51
47
 
52
48
  def current_admin
53
- TestUser.new('Bob', true)
49
+ User.new(id: 2, name: 'Bob', admin: true)
54
50
  end
55
51
 
56
52
  def render_new_user
57
- render :json => TestUser.new('pete', false), :serializer => AdminUserSerializer
53
+ render json: User.new(id: 1, name: 'Pete', admin: false), serializer: AdminUserSerializer, adapter: :json_api
58
54
  end
59
55
  end
60
56
 
@@ -62,6 +58,6 @@ class SerializationScopeNameTest < ActionController::TestCase
62
58
 
63
59
  def test_override_scope_name_with_controller
64
60
  get :render_new_user
65
- assert_equal '{"admin_user":{"admin":true}}', @response.body
61
+ assert_equal '{"data":{"id":"1","type":"users","attributes":{"admin?":true}}}', @response.body
66
62
  end
67
63
  end
@@ -0,0 +1,435 @@
1
+ require 'test_helper'
2
+
3
+ module ActionController
4
+ module Serialization
5
+ class ImplicitSerializerTest < ActionController::TestCase
6
+ include ActiveSupport::Testing::Stream
7
+ class ImplicitSerializationTestController < ActionController::Base
8
+ include SerializationTesting
9
+ def render_using_implicit_serializer
10
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
11
+ render json: @profile
12
+ end
13
+
14
+ def render_using_default_adapter_root
15
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
16
+ render json: @profile
17
+ end
18
+
19
+ def render_array_using_custom_root
20
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
21
+ render json: [@profile], root: 'custom_root'
22
+ end
23
+
24
+ def render_array_that_is_empty_using_custom_root
25
+ render json: [], root: 'custom_root'
26
+ end
27
+
28
+ def render_object_using_custom_root
29
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
30
+ render json: @profile, root: 'custom_root'
31
+ end
32
+
33
+ def render_array_using_implicit_serializer
34
+ array = [
35
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
36
+ Profile.new(name: 'Name 2', description: 'Description 2', comments: 'Comments 2')
37
+ ]
38
+ render json: array
39
+ end
40
+
41
+ def render_array_using_implicit_serializer_and_meta
42
+ @profiles = [
43
+ Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
44
+ ]
45
+ render json: @profiles, meta: { total: 10 }
46
+ end
47
+
48
+ def render_object_with_cache_enabled
49
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
50
+ @author = Author.new(id: 1, name: 'Joao Moura.')
51
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [@comment], author: @author)
52
+
53
+ generate_cached_serializer(@post)
54
+
55
+ @post.title = 'ZOMG a New Post'
56
+ render json: @post
57
+ end
58
+
59
+ def render_json_object_without_serializer
60
+ render json: { error: 'Result is Invalid' }
61
+ end
62
+
63
+ def render_json_array_object_without_serializer
64
+ render json: [{ error: 'Result is Invalid' }]
65
+ end
66
+
67
+ def update_and_render_object_with_cache_enabled
68
+ @post.updated_at = Time.now
69
+
70
+ generate_cached_serializer(@post)
71
+ render json: @post
72
+ end
73
+
74
+ def render_object_expired_with_cache_enabled
75
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
76
+ author = Author.new(id: 1, name: 'Joao Moura.')
77
+ post = Post.new(id: 1, title: 'New Post', body: 'Body', comments: [comment], author: author)
78
+
79
+ generate_cached_serializer(post)
80
+
81
+ post.title = 'ZOMG a New Post'
82
+
83
+ expires_in = [
84
+ PostSerializer._cache_options[:expires_in],
85
+ CommentSerializer._cache_options[:expires_in],
86
+ ].max + 200
87
+
88
+ Timecop.travel(Time.zone.now + expires_in) do
89
+ render json: post
90
+ end
91
+ end
92
+
93
+ def render_changed_object_with_cache_enabled
94
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
95
+ author = Author.new(id: 1, name: 'Joao Moura.')
96
+ post = Post.new(id: 1, title: 'ZOMG a New Post', body: 'Body', comments: [comment], author: author)
97
+
98
+ render json: post
99
+ end
100
+
101
+ def render_fragment_changed_object_with_only_cache_enabled
102
+ author = Author.new(id: 1, name: 'Joao Moura.')
103
+ role = Role.new(id: 42, name: 'ZOMG A ROLE', description: 'DESCRIPTION HERE', author: author)
104
+
105
+ generate_cached_serializer(role)
106
+ role.name = 'lol'
107
+ role.description = 'HUEHUEBRBR'
108
+
109
+ render json: role
110
+ end
111
+
112
+ def render_fragment_changed_object_with_except_cache_enabled
113
+ author = Author.new(id: 1, name: 'Joao Moura.')
114
+ bio = Bio.new(id: 42, content: 'ZOMG A ROLE', rating: 5, author: author)
115
+
116
+ generate_cached_serializer(bio)
117
+ bio.content = 'lol'
118
+ bio.rating = 0
119
+
120
+ render json: bio
121
+ end
122
+
123
+ def render_fragment_changed_object_with_relationship
124
+ comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
125
+ comment2 = Comment.new(id: 1, body: 'ZOMG AN UPDATED-BUT-NOT-CACHE-EXPIRED COMMENT')
126
+ like = Like.new(id: 1, likeable: comment, time: 3.days.ago)
127
+
128
+ generate_cached_serializer(like)
129
+ like.likable = comment2
130
+ like.time = Time.zone.now.to_s
131
+
132
+ render json: like
133
+ end
134
+ end
135
+
136
+ tests ImplicitSerializationTestController
137
+
138
+ # We just have Null for now, this will change
139
+ def test_render_using_implicit_serializer
140
+ get :render_using_implicit_serializer
141
+
142
+ expected = {
143
+ name: 'Name 1',
144
+ description: 'Description 1'
145
+ }
146
+
147
+ assert_equal 'application/json', @response.content_type
148
+ assert_equal expected.to_json, @response.body
149
+ end
150
+
151
+ def test_render_using_default_root
152
+ with_adapter :json_api do
153
+ get :render_using_default_adapter_root
154
+ end
155
+ expected = {
156
+ data: {
157
+ id: assigns(:profile).id.to_s,
158
+ type: 'profiles',
159
+ attributes: {
160
+ name: 'Name 1',
161
+ description: 'Description 1'
162
+ }
163
+ }
164
+ }
165
+
166
+ assert_equal 'application/json', @response.content_type
167
+ assert_equal expected.to_json, @response.body
168
+ end
169
+
170
+ def test_render_array_using_custom_root
171
+ with_adapter :json do
172
+ get :render_array_using_custom_root
173
+ end
174
+ expected = { custom_root: [{ name: 'Name 1', description: 'Description 1' }] }
175
+ assert_equal 'application/json', @response.content_type
176
+ assert_equal expected.to_json, @response.body
177
+ end
178
+
179
+ def test_render_array_that_is_empty_using_custom_root
180
+ with_adapter :json do
181
+ get :render_array_that_is_empty_using_custom_root
182
+ end
183
+
184
+ expected = { custom_root: [] }
185
+ assert_equal 'application/json', @response.content_type
186
+ assert_equal expected.to_json, @response.body
187
+ end
188
+
189
+ def test_render_object_using_custom_root
190
+ with_adapter :json do
191
+ get :render_object_using_custom_root
192
+ end
193
+
194
+ expected = { custom_root: { name: 'Name 1', description: 'Description 1' } }
195
+ assert_equal 'application/json', @response.content_type
196
+ assert_equal expected.to_json, @response.body
197
+ end
198
+
199
+ def test_render_json_object_without_serializer
200
+ get :render_json_object_without_serializer
201
+
202
+ assert_equal 'application/json', @response.content_type
203
+ expected_body = { error: 'Result is Invalid' }
204
+ assert_equal expected_body.to_json, @response.body
205
+ end
206
+
207
+ def test_render_json_array_object_without_serializer
208
+ get :render_json_array_object_without_serializer
209
+
210
+ assert_equal 'application/json', @response.content_type
211
+ expected_body = [{ error: 'Result is Invalid' }]
212
+ assert_equal expected_body.to_json, @response.body
213
+ end
214
+
215
+ def test_render_array_using_implicit_serializer
216
+ get :render_array_using_implicit_serializer
217
+ assert_equal 'application/json', @response.content_type
218
+
219
+ expected = [
220
+ {
221
+ name: 'Name 1',
222
+ description: 'Description 1'
223
+ },
224
+ {
225
+ name: 'Name 2',
226
+ description: 'Description 2'
227
+ }
228
+ ]
229
+
230
+ assert_equal expected.to_json, @response.body
231
+ end
232
+
233
+ def test_render_array_using_implicit_serializer_and_meta
234
+ with_adapter :json_api do
235
+ get :render_array_using_implicit_serializer_and_meta
236
+ end
237
+ expected = {
238
+ data: [
239
+ {
240
+ id: assigns(:profiles).first.id.to_s,
241
+ type: 'profiles',
242
+ attributes: {
243
+ name: 'Name 1',
244
+ description: 'Description 1'
245
+ }
246
+ }
247
+ ],
248
+ meta: {
249
+ total: 10
250
+ }
251
+ }
252
+
253
+ assert_equal 'application/json', @response.content_type
254
+ assert_equal expected.to_json, @response.body
255
+ end
256
+
257
+ def test_render_with_cache_enable
258
+ expected = {
259
+ id: 1,
260
+ title: 'New Post',
261
+ body: 'Body',
262
+ comments: [
263
+ {
264
+ id: 1,
265
+ body: 'ZOMG A COMMENT' }
266
+ ],
267
+ blog: {
268
+ id: 999,
269
+ name: 'Custom blog'
270
+ },
271
+ author: {
272
+ id: 1,
273
+ name: 'Joao Moura.'
274
+ }
275
+ }
276
+
277
+ ActionController::Base.cache_store.clear
278
+ Timecop.freeze(Time.zone.now) do
279
+ get :render_object_with_cache_enabled
280
+
281
+ assert_equal 'application/json', @response.content_type
282
+ assert_equal expected.to_json, @response.body
283
+
284
+ get :render_changed_object_with_cache_enabled
285
+ assert_equal expected.to_json, @response.body
286
+ end
287
+
288
+ ActionController::Base.cache_store.clear
289
+ get :render_changed_object_with_cache_enabled
290
+ assert_not_equal expected.to_json, @response.body
291
+ end
292
+
293
+ def test_render_with_cache_enable_and_expired
294
+ ActionController::Base.cache_store.clear
295
+ get :render_object_expired_with_cache_enabled
296
+
297
+ expected = {
298
+ id: 1,
299
+ title: 'ZOMG a New Post',
300
+ body: 'Body',
301
+ comments: [
302
+ {
303
+ id: 1,
304
+ body: 'ZOMG A COMMENT' }
305
+ ],
306
+ blog: {
307
+ id: 999,
308
+ name: 'Custom blog'
309
+ },
310
+ author: {
311
+ id: 1,
312
+ name: 'Joao Moura.'
313
+ }
314
+ }
315
+
316
+ assert_equal 'application/json', @response.content_type
317
+ actual = @response.body
318
+ expected = expected.to_json
319
+ if ENV['APPVEYOR'] && actual != expected
320
+ skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
321
+ else
322
+ assert_equal actual, expected
323
+ end
324
+ end
325
+
326
+ def test_render_with_fragment_only_cache_enable
327
+ ActionController::Base.cache_store.clear
328
+ get :render_fragment_changed_object_with_only_cache_enabled
329
+ response = JSON.parse(@response.body)
330
+
331
+ assert_equal 'application/json', @response.content_type
332
+ assert_equal 'ZOMG A ROLE', response['name']
333
+ assert_equal 'HUEHUEBRBR', response['description']
334
+ end
335
+
336
+ def test_render_with_fragment_except_cache_enable
337
+ ActionController::Base.cache_store.clear
338
+ get :render_fragment_changed_object_with_except_cache_enabled
339
+ response = JSON.parse(@response.body)
340
+
341
+ assert_equal 'application/json', @response.content_type
342
+ assert_equal 5, response['rating']
343
+ assert_equal 'lol', response['content']
344
+ end
345
+
346
+ def test_render_fragment_changed_object_with_relationship
347
+ ActionController::Base.cache_store.clear
348
+
349
+ Timecop.freeze(Time.zone.now) do
350
+ get :render_fragment_changed_object_with_relationship
351
+ response = JSON.parse(@response.body)
352
+
353
+ expected_return = {
354
+ 'id' => 1,
355
+ 'time' => Time.zone.now.to_s,
356
+ 'likeable' => {
357
+ 'id' => 1,
358
+ 'body' => 'ZOMG A COMMENT'
359
+ }
360
+ }
361
+
362
+ assert_equal 'application/json', @response.content_type
363
+ assert_equal expected_return, response
364
+ end
365
+ end
366
+
367
+ def test_cache_expiration_on_update
368
+ ActionController::Base.cache_store.clear
369
+ get :render_object_with_cache_enabled
370
+
371
+ expected = {
372
+ id: 1,
373
+ title: 'ZOMG a New Post',
374
+ body: 'Body',
375
+ comments: [
376
+ {
377
+ id: 1,
378
+ body: 'ZOMG A COMMENT' }
379
+ ],
380
+ blog: {
381
+ id: 999,
382
+ name: 'Custom blog'
383
+ },
384
+ author: {
385
+ id: 1,
386
+ name: 'Joao Moura.'
387
+ }
388
+ }
389
+
390
+ get :update_and_render_object_with_cache_enabled
391
+
392
+ assert_equal 'application/json', @response.content_type
393
+ actual = @response.body
394
+ expected = expected.to_json
395
+ if ENV['APPVEYOR'] && actual != expected
396
+ skip('Cache expiration tests sometimes fail on Appveyor. FIXME :)')
397
+ else
398
+ assert_equal actual, expected
399
+ end
400
+ end
401
+
402
+ def test_warn_overridding_use_adapter_as_falsy_on_controller_instance
403
+ controller = Class.new(ImplicitSerializationTestController) do
404
+ def use_adapter?
405
+ false
406
+ end
407
+ end.new
408
+ assert_match(/adapter: false/, (capture(:stderr) do
409
+ controller.get_serializer(Profile.new)
410
+ end))
411
+ end
412
+
413
+ def test_dont_warn_overridding_use_adapter_as_truthy_on_controller_instance
414
+ controller = Class.new(ImplicitSerializationTestController) do
415
+ def use_adapter?
416
+ true
417
+ end
418
+ end.new
419
+ assert_equal '', (capture(:stderr) do
420
+ controller.get_serializer(Profile.new)
421
+ end)
422
+ end
423
+
424
+ def test_render_event_is_emmited
425
+ ActiveSupport::Notifications.subscribe('render.active_model_serializers') do |name|
426
+ @name = name
427
+ end
428
+
429
+ get :render_using_implicit_serializer
430
+
431
+ assert_equal 'render.active_model_serializers', @name
432
+ end
433
+ end
434
+ end
435
+ end