active_model_serializers_custom 0.10.90

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 (215) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE.md +29 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +15 -0
  4. data/.gitignore +35 -0
  5. data/.rubocop.yml +109 -0
  6. data/.simplecov +110 -0
  7. data/.travis.yml +63 -0
  8. data/CHANGELOG.md +727 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/CONTRIBUTING.md +105 -0
  11. data/Gemfile +74 -0
  12. data/MIT-LICENSE +22 -0
  13. data/README.md +305 -0
  14. data/Rakefile +76 -0
  15. data/active_model_serializers.gemspec +64 -0
  16. data/appveyor.yml +28 -0
  17. data/bin/bench +171 -0
  18. data/bin/bench_regression +316 -0
  19. data/bin/rubocop +38 -0
  20. data/bin/serve_benchmark +39 -0
  21. data/docs/README.md +41 -0
  22. data/docs/STYLE.md +58 -0
  23. data/docs/general/adapters.md +269 -0
  24. data/docs/general/caching.md +58 -0
  25. data/docs/general/configuration_options.md +185 -0
  26. data/docs/general/deserialization.md +100 -0
  27. data/docs/general/fields.md +31 -0
  28. data/docs/general/getting_started.md +133 -0
  29. data/docs/general/instrumentation.md +40 -0
  30. data/docs/general/key_transforms.md +40 -0
  31. data/docs/general/logging.md +21 -0
  32. data/docs/general/rendering.md +293 -0
  33. data/docs/general/serializers.md +495 -0
  34. data/docs/how-open-source-maintained.jpg +0 -0
  35. data/docs/howto/add_pagination_links.md +138 -0
  36. data/docs/howto/add_relationship_links.md +140 -0
  37. data/docs/howto/add_root_key.md +62 -0
  38. data/docs/howto/grape_integration.md +42 -0
  39. data/docs/howto/outside_controller_use.md +66 -0
  40. data/docs/howto/passing_arbitrary_options.md +27 -0
  41. data/docs/howto/serialize_poro.md +73 -0
  42. data/docs/howto/test.md +154 -0
  43. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  44. data/docs/integrations/ember-and-json-api.md +147 -0
  45. data/docs/integrations/grape.md +19 -0
  46. data/docs/jsonapi/errors.md +56 -0
  47. data/docs/jsonapi/schema.md +151 -0
  48. data/docs/jsonapi/schema/schema.json +366 -0
  49. data/docs/rfcs/0000-namespace.md +106 -0
  50. data/docs/rfcs/template.md +15 -0
  51. data/lib/action_controller/serialization.rb +76 -0
  52. data/lib/active_model/serializable_resource.rb +13 -0
  53. data/lib/active_model/serializer.rb +418 -0
  54. data/lib/active_model/serializer/adapter.rb +26 -0
  55. data/lib/active_model/serializer/adapter/attributes.rb +17 -0
  56. data/lib/active_model/serializer/adapter/base.rb +20 -0
  57. data/lib/active_model/serializer/adapter/json.rb +17 -0
  58. data/lib/active_model/serializer/adapter/json_api.rb +17 -0
  59. data/lib/active_model/serializer/adapter/null.rb +17 -0
  60. data/lib/active_model/serializer/array_serializer.rb +14 -0
  61. data/lib/active_model/serializer/association.rb +91 -0
  62. data/lib/active_model/serializer/attribute.rb +27 -0
  63. data/lib/active_model/serializer/belongs_to_reflection.rb +13 -0
  64. data/lib/active_model/serializer/collection_serializer.rb +90 -0
  65. data/lib/active_model/serializer/concerns/caching.rb +304 -0
  66. data/lib/active_model/serializer/error_serializer.rb +16 -0
  67. data/lib/active_model/serializer/errors_serializer.rb +34 -0
  68. data/lib/active_model/serializer/field.rb +92 -0
  69. data/lib/active_model/serializer/fieldset.rb +33 -0
  70. data/lib/active_model/serializer/has_many_reflection.rb +12 -0
  71. data/lib/active_model/serializer/has_one_reflection.rb +9 -0
  72. data/lib/active_model/serializer/lazy_association.rb +99 -0
  73. data/lib/active_model/serializer/link.rb +23 -0
  74. data/lib/active_model/serializer/lint.rb +152 -0
  75. data/lib/active_model/serializer/null.rb +19 -0
  76. data/lib/active_model/serializer/reflection.rb +212 -0
  77. data/lib/active_model/serializer/version.rb +7 -0
  78. data/lib/active_model_serializers.rb +63 -0
  79. data/lib/active_model_serializers/adapter.rb +100 -0
  80. data/lib/active_model_serializers/adapter/attributes.rb +15 -0
  81. data/lib/active_model_serializers/adapter/base.rb +85 -0
  82. data/lib/active_model_serializers/adapter/json.rb +23 -0
  83. data/lib/active_model_serializers/adapter/json_api.rb +535 -0
  84. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +215 -0
  85. data/lib/active_model_serializers/adapter/json_api/error.rb +98 -0
  86. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +51 -0
  87. data/lib/active_model_serializers/adapter/json_api/link.rb +85 -0
  88. data/lib/active_model_serializers/adapter/json_api/meta.rb +39 -0
  89. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +90 -0
  90. data/lib/active_model_serializers/adapter/json_api/relationship.rb +106 -0
  91. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +68 -0
  92. data/lib/active_model_serializers/adapter/null.rb +11 -0
  93. data/lib/active_model_serializers/callbacks.rb +57 -0
  94. data/lib/active_model_serializers/deprecate.rb +56 -0
  95. data/lib/active_model_serializers/deserialization.rb +17 -0
  96. data/lib/active_model_serializers/json_pointer.rb +16 -0
  97. data/lib/active_model_serializers/logging.rb +124 -0
  98. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  99. data/lib/active_model_serializers/model.rb +132 -0
  100. data/lib/active_model_serializers/railtie.rb +52 -0
  101. data/lib/active_model_serializers/register_jsonapi_renderer.rb +80 -0
  102. data/lib/active_model_serializers/serializable_resource.rb +84 -0
  103. data/lib/active_model_serializers/serialization_context.rb +41 -0
  104. data/lib/active_model_serializers/test.rb +9 -0
  105. data/lib/active_model_serializers/test/schema.rb +140 -0
  106. data/lib/active_model_serializers/test/serializer.rb +127 -0
  107. data/lib/generators/rails/USAGE +6 -0
  108. data/lib/generators/rails/resource_override.rb +12 -0
  109. data/lib/generators/rails/serializer_generator.rb +38 -0
  110. data/lib/generators/rails/templates/serializer.rb.erb +8 -0
  111. data/lib/grape/active_model_serializers.rb +18 -0
  112. data/lib/grape/formatters/active_model_serializers.rb +34 -0
  113. data/lib/grape/helpers/active_model_serializers.rb +19 -0
  114. data/lib/tasks/rubocop.rake +55 -0
  115. data/test/action_controller/adapter_selector_test.rb +64 -0
  116. data/test/action_controller/explicit_serializer_test.rb +137 -0
  117. data/test/action_controller/json/include_test.rb +248 -0
  118. data/test/action_controller/json_api/deserialization_test.rb +114 -0
  119. data/test/action_controller/json_api/errors_test.rb +42 -0
  120. data/test/action_controller/json_api/fields_test.rb +68 -0
  121. data/test/action_controller/json_api/linked_test.rb +204 -0
  122. data/test/action_controller/json_api/pagination_test.rb +126 -0
  123. data/test/action_controller/json_api/transform_test.rb +191 -0
  124. data/test/action_controller/lookup_proc_test.rb +51 -0
  125. data/test/action_controller/namespace_lookup_test.rb +239 -0
  126. data/test/action_controller/serialization_scope_name_test.rb +237 -0
  127. data/test/action_controller/serialization_test.rb +480 -0
  128. data/test/active_model_serializers/adapter_for_test.rb +210 -0
  129. data/test/active_model_serializers/json_pointer_test.rb +24 -0
  130. data/test/active_model_serializers/logging_test.rb +79 -0
  131. data/test/active_model_serializers/model_test.rb +144 -0
  132. data/test/active_model_serializers/railtie_test_isolated.rb +70 -0
  133. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  134. data/test/active_model_serializers/serialization_context_test_isolated.rb +73 -0
  135. data/test/active_model_serializers/test/schema_test.rb +133 -0
  136. data/test/active_model_serializers/test/serializer_test.rb +64 -0
  137. data/test/active_record_test.rb +11 -0
  138. data/test/adapter/attributes_test.rb +42 -0
  139. data/test/adapter/deprecation_test.rb +102 -0
  140. data/test/adapter/json/belongs_to_test.rb +47 -0
  141. data/test/adapter/json/collection_test.rb +106 -0
  142. data/test/adapter/json/has_many_test.rb +55 -0
  143. data/test/adapter/json/transform_test.rb +95 -0
  144. data/test/adapter/json_api/belongs_to_test.rb +157 -0
  145. data/test/adapter/json_api/collection_test.rb +98 -0
  146. data/test/adapter/json_api/errors_test.rb +78 -0
  147. data/test/adapter/json_api/fields_test.rb +98 -0
  148. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +98 -0
  149. data/test/adapter/json_api/has_many_test.rb +175 -0
  150. data/test/adapter/json_api/has_one_test.rb +82 -0
  151. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  152. data/test/adapter/json_api/json_api_test.rb +35 -0
  153. data/test/adapter/json_api/linked_test.rb +415 -0
  154. data/test/adapter/json_api/links_test.rb +112 -0
  155. data/test/adapter/json_api/pagination_links_test.rb +208 -0
  156. data/test/adapter/json_api/parse_test.rb +139 -0
  157. data/test/adapter/json_api/relationship_test.rb +399 -0
  158. data/test/adapter/json_api/resource_meta_test.rb +102 -0
  159. data/test/adapter/json_api/toplevel_jsonapi_test.rb +84 -0
  160. data/test/adapter/json_api/transform_test.rb +514 -0
  161. data/test/adapter/json_api/type_test.rb +195 -0
  162. data/test/adapter/json_test.rb +48 -0
  163. data/test/adapter/null_test.rb +24 -0
  164. data/test/adapter/polymorphic_test.rb +220 -0
  165. data/test/adapter_test.rb +69 -0
  166. data/test/array_serializer_test.rb +24 -0
  167. data/test/benchmark/app.rb +67 -0
  168. data/test/benchmark/benchmarking_support.rb +69 -0
  169. data/test/benchmark/bm_active_record.rb +83 -0
  170. data/test/benchmark/bm_adapter.rb +40 -0
  171. data/test/benchmark/bm_caching.rb +121 -0
  172. data/test/benchmark/bm_lookup_chain.rb +85 -0
  173. data/test/benchmark/bm_transform.rb +47 -0
  174. data/test/benchmark/config.ru +3 -0
  175. data/test/benchmark/controllers.rb +85 -0
  176. data/test/benchmark/fixtures.rb +221 -0
  177. data/test/cache_test.rb +717 -0
  178. data/test/collection_serializer_test.rb +129 -0
  179. data/test/fixtures/active_record.rb +115 -0
  180. data/test/fixtures/poro.rb +227 -0
  181. data/test/generators/scaffold_controller_generator_test.rb +26 -0
  182. data/test/generators/serializer_generator_test.rb +77 -0
  183. data/test/grape_test.rb +198 -0
  184. data/test/lint_test.rb +51 -0
  185. data/test/logger_test.rb +22 -0
  186. data/test/poro_test.rb +11 -0
  187. data/test/serializable_resource_test.rb +81 -0
  188. data/test/serializers/association_macros_test.rb +39 -0
  189. data/test/serializers/associations_test.rb +520 -0
  190. data/test/serializers/attribute_test.rb +155 -0
  191. data/test/serializers/attributes_test.rb +54 -0
  192. data/test/serializers/caching_configuration_test_isolated.rb +172 -0
  193. data/test/serializers/configuration_test.rb +34 -0
  194. data/test/serializers/fieldset_test.rb +16 -0
  195. data/test/serializers/meta_test.rb +204 -0
  196. data/test/serializers/options_test.rb +34 -0
  197. data/test/serializers/read_attribute_for_serialization_test.rb +81 -0
  198. data/test/serializers/reflection_test.rb +481 -0
  199. data/test/serializers/root_test.rb +23 -0
  200. data/test/serializers/serialization_test.rb +57 -0
  201. data/test/serializers/serializer_for_test.rb +138 -0
  202. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  203. data/test/support/custom_schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  204. data/test/support/isolated_unit.rb +86 -0
  205. data/test/support/rails5_shims.rb +55 -0
  206. data/test/support/rails_app.rb +40 -0
  207. data/test/support/schemas/active_model_serializers/test/schema_test/my/index.json +6 -0
  208. data/test/support/schemas/active_model_serializers/test/schema_test/my/show.json +6 -0
  209. data/test/support/schemas/custom/show.json +7 -0
  210. data/test/support/schemas/hyper_schema.json +93 -0
  211. data/test/support/schemas/render_using_json_api.json +43 -0
  212. data/test/support/schemas/simple_json_pointers.json +10 -0
  213. data/test/support/serialization_testing.rb +81 -0
  214. data/test/test_helper.rb +72 -0
  215. metadata +622 -0
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModelSerializers
6
+ module Adapter
7
+ class JsonApiTest < ActiveSupport::TestCase
8
+ def setup
9
+ ActionController::Base.cache_store.clear
10
+ @author = Author.new(id: 1, name: 'Steve K.')
11
+ @post = Post.new(id: 1, title: 'New Post', body: 'Body')
12
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
13
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
14
+ @post.comments = [@first_comment, @second_comment]
15
+ @first_comment.post = @post
16
+ @second_comment.post = @post
17
+ @post.author = @author
18
+ @blog = Blog.new(id: 1, name: 'My Blog!!')
19
+ @post.blog = @blog
20
+ end
21
+
22
+ def test_custom_keys
23
+ serializer = PostWithCustomKeysSerializer.new(@post)
24
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
25
+
26
+ assert_equal({
27
+ reviews: { data: [{ type: 'comments', id: '1' },
28
+ { type: 'comments', id: '2' }] },
29
+ writer: { data: { type: 'authors', id: '1' } },
30
+ site: { data: { type: 'blogs', id: '1' } }
31
+ }, adapter.serializable_hash[:data][:relationships])
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,415 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class NestedPost < ::Model; associations :nested_posts end
6
+ class NestedPostSerializer < ActiveModel::Serializer
7
+ has_many :nested_posts
8
+ end
9
+ module ActiveModelSerializers
10
+ module Adapter
11
+ class JsonApi
12
+ class LinkedTest < ActiveSupport::TestCase
13
+ def setup
14
+ @author1 = Author.new(id: 1, name: 'Steve K.')
15
+ @author2 = Author.new(id: 2, name: 'Tenderlove')
16
+ @bio1 = Bio.new(id: 1, content: 'AMS Contributor')
17
+ @bio2 = Bio.new(id: 2, content: 'Rails Contributor')
18
+ @first_post = Post.new(id: 10, title: 'Hello!!', body: 'Hello, world!!')
19
+ @second_post = Post.new(id: 20, title: 'New Post', body: 'Body')
20
+ @third_post = Post.new(id: 30, title: 'Yet Another Post', body: 'Body')
21
+ @blog = Blog.new(name: 'AMS Blog')
22
+ @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
23
+ @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
24
+ @first_post.blog = @blog
25
+ @second_post.blog = @blog
26
+ @third_post.blog = nil
27
+ @first_post.comments = [@first_comment, @second_comment]
28
+ @second_post.comments = []
29
+ @third_post.comments = []
30
+ @first_post.author = @author1
31
+ @second_post.author = @author2
32
+ @third_post.author = @author1
33
+ @first_comment.post = @first_post
34
+ @first_comment.author = nil
35
+ @second_comment.post = @first_post
36
+ @second_comment.author = nil
37
+ @author1.posts = [@first_post, @third_post]
38
+ @author1.bio = @bio1
39
+ @author1.roles = []
40
+ @author2.posts = [@second_post]
41
+ @author2.bio = @bio2
42
+ @author2.roles = []
43
+ @bio1.author = @author1
44
+ @bio2.author = @author2
45
+ end
46
+
47
+ def test_include_multiple_posts_and_linked_array
48
+ serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_post, @second_post])
49
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(
50
+ serializer,
51
+ include: [:comments, author: [:bio]]
52
+ )
53
+ alt_adapter = ActiveModelSerializers::Adapter::JsonApi.new(
54
+ serializer,
55
+ include: [:comments, author: [:bio]]
56
+ )
57
+
58
+ expected = {
59
+ data: [
60
+ {
61
+ id: '10',
62
+ type: 'posts',
63
+ attributes: {
64
+ title: 'Hello!!',
65
+ body: 'Hello, world!!'
66
+ },
67
+ relationships: {
68
+ comments: { data: [{ type: 'comments', id: '1' }, { type: 'comments', id: '2' }] },
69
+ blog: { data: { type: 'blogs', id: '999' } },
70
+ author: { data: { type: 'authors', id: '1' } }
71
+ }
72
+ },
73
+ {
74
+ id: '20',
75
+ type: 'posts',
76
+ attributes: {
77
+ title: 'New Post',
78
+ body: 'Body'
79
+ },
80
+ relationships: {
81
+ comments: { data: [] },
82
+ blog: { data: { type: 'blogs', id: '999' } },
83
+ author: { data: { type: 'authors', id: '2' } }
84
+ }
85
+ }
86
+ ],
87
+ included: [
88
+ {
89
+ id: '1',
90
+ type: 'comments',
91
+ attributes: {
92
+ body: 'ZOMG A COMMENT'
93
+ },
94
+ relationships: {
95
+ post: { data: { type: 'posts', id: '10' } },
96
+ author: { data: nil }
97
+ }
98
+ }, {
99
+ id: '2',
100
+ type: 'comments',
101
+ attributes: {
102
+ body: 'ZOMG ANOTHER COMMENT'
103
+ },
104
+ relationships: {
105
+ post: { data: { type: 'posts', id: '10' } },
106
+ author: { data: nil }
107
+ }
108
+ }, {
109
+ id: '1',
110
+ type: 'authors',
111
+ attributes: {
112
+ name: 'Steve K.'
113
+ },
114
+ relationships: {
115
+ posts: { data: [{ type: 'posts', id: '10' }, { type: 'posts', id: '30' }] },
116
+ roles: { data: [] },
117
+ bio: { data: { type: 'bios', id: '1' } }
118
+ }
119
+ }, {
120
+ id: '1',
121
+ type: 'bios',
122
+ attributes: {
123
+ content: 'AMS Contributor',
124
+ rating: nil
125
+ },
126
+ relationships: {
127
+ author: { data: { type: 'authors', id: '1' } }
128
+ }
129
+ }, {
130
+ id: '2',
131
+ type: 'authors',
132
+ attributes: {
133
+ name: 'Tenderlove'
134
+ },
135
+ relationships: {
136
+ posts: { data: [{ type: 'posts', id: '20' }] },
137
+ roles: { data: [] },
138
+ bio: { data: { type: 'bios', id: '2' } }
139
+ }
140
+ }, {
141
+ id: '2',
142
+ type: 'bios',
143
+ attributes: {
144
+ rating: nil,
145
+ content: 'Rails Contributor'
146
+ },
147
+ relationships: {
148
+ author: { data: { type: 'authors', id: '2' } }
149
+ }
150
+ }
151
+ ]
152
+ }
153
+ assert_equal expected, adapter.serializable_hash
154
+ assert_equal expected, alt_adapter.serializable_hash
155
+ end
156
+
157
+ def test_include_multiple_posts_and_linked
158
+ serializer = BioSerializer.new @bio1
159
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(
160
+ serializer,
161
+ include: [author: [:posts]]
162
+ )
163
+ alt_adapter = ActiveModelSerializers::Adapter::JsonApi.new(
164
+ serializer,
165
+ include: [author: [:posts]]
166
+ )
167
+
168
+ expected = [
169
+ {
170
+ id: '1',
171
+ type: 'authors',
172
+ attributes: {
173
+ name: 'Steve K.'
174
+ },
175
+ relationships: {
176
+ posts: { data: [{ type: 'posts', id: '10' }, { type: 'posts', id: '30' }] },
177
+ roles: { data: [] },
178
+ bio: { data: { type: 'bios', id: '1' } }
179
+ }
180
+ }, {
181
+ id: '10',
182
+ type: 'posts',
183
+ attributes: {
184
+ title: 'Hello!!',
185
+ body: 'Hello, world!!'
186
+ },
187
+ relationships: {
188
+ comments: { data: [{ type: 'comments', id: '1' }, { type: 'comments', id: '2' }] },
189
+ blog: { data: { type: 'blogs', id: '999' } },
190
+ author: { data: { type: 'authors', id: '1' } }
191
+ }
192
+ }, {
193
+ id: '30',
194
+ type: 'posts',
195
+ attributes: {
196
+ title: 'Yet Another Post',
197
+ body: 'Body'
198
+ },
199
+ relationships: {
200
+ comments: { data: [] },
201
+ blog: { data: { type: 'blogs', id: '999' } },
202
+ author: { data: { type: 'authors', id: '1' } }
203
+ }
204
+ }
205
+ ]
206
+
207
+ assert_equal expected, adapter.serializable_hash[:included]
208
+ assert_equal expected, alt_adapter.serializable_hash[:included]
209
+ end
210
+
211
+ def test_underscore_model_namespace_for_linked_resource_type
212
+ spammy_post = Post.new(id: 123)
213
+ spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
214
+ serializer = SpammyPostSerializer.new(spammy_post)
215
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
216
+ relationships = adapter.serializable_hash[:data][:relationships]
217
+ expected = {
218
+ related: {
219
+ data: [{
220
+ type: 'spam-unrelated-links',
221
+ id: '456'
222
+ }]
223
+ }
224
+ }
225
+ assert_equal expected, relationships
226
+ end
227
+
228
+ def test_underscore_model_namespace_with_namespace_separator_for_linked_resource_type
229
+ spammy_post = Post.new(id: 123)
230
+ spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
231
+ serializer = SpammyPostSerializer.new(spammy_post)
232
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
233
+ relationships = with_namespace_separator '--' do
234
+ adapter.serializable_hash[:data][:relationships]
235
+ end
236
+ expected = {
237
+ related: {
238
+ data: [{
239
+ type: 'spam--unrelated-links',
240
+ id: '456'
241
+ }]
242
+ }
243
+ }
244
+ assert_equal expected, relationships
245
+ end
246
+
247
+ def test_multiple_references_to_same_resource
248
+ serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_comment, @second_comment])
249
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(
250
+ serializer,
251
+ include: [:post]
252
+ )
253
+
254
+ expected = [
255
+ {
256
+ id: '10',
257
+ type: 'posts',
258
+ attributes: {
259
+ title: 'Hello!!',
260
+ body: 'Hello, world!!'
261
+ },
262
+ relationships: {
263
+ comments: {
264
+ data: [{ type: 'comments', id: '1' }, { type: 'comments', id: '2' }]
265
+ },
266
+ blog: {
267
+ data: { type: 'blogs', id: '999' }
268
+ },
269
+ author: {
270
+ data: { type: 'authors', id: '1' }
271
+ }
272
+ }
273
+ }
274
+ ]
275
+
276
+ assert_equal expected, adapter.serializable_hash[:included]
277
+ end
278
+
279
+ def test_nil_link_with_specified_serializer
280
+ @first_post.author = nil
281
+ serializer = PostPreviewSerializer.new(@first_post)
282
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(
283
+ serializer,
284
+ include: [:author]
285
+ )
286
+
287
+ expected = {
288
+ data: {
289
+ id: '10',
290
+ type: 'posts',
291
+ attributes: {
292
+ title: 'Hello!!',
293
+ body: 'Hello, world!!'
294
+ },
295
+ relationships: {
296
+ comments: { data: [{ type: 'comments', id: '1' }, { type: 'comments', id: '2' }] },
297
+ author: { data: nil }
298
+ }
299
+ }
300
+ }
301
+ assert_equal expected, adapter.serializable_hash
302
+ end
303
+ end
304
+
305
+ class NoDuplicatesTest < ActiveSupport::TestCase
306
+ class Post < ::Model; associations :author end
307
+ class Author < ::Model; associations :posts, :roles, :bio end
308
+
309
+ class PostSerializer < ActiveModel::Serializer
310
+ type 'posts'
311
+ belongs_to :author
312
+ end
313
+
314
+ class AuthorSerializer < ActiveModel::Serializer
315
+ type 'authors'
316
+ has_many :posts
317
+ end
318
+
319
+ def setup
320
+ @author = Author.new(id: 1, posts: [], roles: [], bio: nil)
321
+ @post1 = Post.new(id: 1, author: @author)
322
+ @post2 = Post.new(id: 2, author: @author)
323
+ @author.posts << @post1
324
+ @author.posts << @post2
325
+
326
+ @nestedpost1 = NestedPost.new(id: 1, nested_posts: [])
327
+ @nestedpost2 = NestedPost.new(id: 2, nested_posts: [])
328
+ @nestedpost1.nested_posts << @nestedpost1
329
+ @nestedpost1.nested_posts << @nestedpost2
330
+ @nestedpost2.nested_posts << @nestedpost1
331
+ @nestedpost2.nested_posts << @nestedpost2
332
+ end
333
+
334
+ def test_no_duplicates
335
+ hash = ActiveModelSerializers::SerializableResource.new(@post1, adapter: :json_api,
336
+ include: '*.*')
337
+ .serializable_hash
338
+ expected = [
339
+ {
340
+ type: 'authors', id: '1',
341
+ relationships: {
342
+ posts: {
343
+ data: [
344
+ { type: 'posts', id: '1' },
345
+ { type: 'posts', id: '2' }
346
+ ]
347
+ }
348
+ }
349
+ },
350
+ {
351
+ type: 'posts', id: '2',
352
+ relationships: {
353
+ author: {
354
+ data: { type: 'authors', id: '1' }
355
+ }
356
+ }
357
+ }
358
+ ]
359
+ assert_equal(expected, hash[:included])
360
+ end
361
+
362
+ def test_no_duplicates_collection
363
+ hash = ActiveModelSerializers::SerializableResource.new(
364
+ [@post1, @post2],
365
+ adapter: :json_api,
366
+ include: '*.*'
367
+ ).serializable_hash
368
+ expected = [
369
+ {
370
+ type: 'authors', id: '1',
371
+ relationships: {
372
+ posts: {
373
+ data: [
374
+ { type: 'posts', id: '1' },
375
+ { type: 'posts', id: '2' }
376
+ ]
377
+ }
378
+ }
379
+ }
380
+ ]
381
+ assert_equal(expected, hash[:included])
382
+ end
383
+
384
+ def test_no_duplicates_global
385
+ hash = ActiveModelSerializers::SerializableResource.new(
386
+ @nestedpost1,
387
+ adapter: :json_api,
388
+ include: '*'
389
+ ).serializable_hash
390
+ expected = [
391
+ type: 'nested-posts', id: '2',
392
+ relationships: {
393
+ :"nested-posts" => {
394
+ data: [
395
+ { type: 'nested-posts', id: '1' },
396
+ { type: 'nested-posts', id: '2' }
397
+ ]
398
+ }
399
+ }
400
+ ]
401
+ assert_equal(expected, hash[:included])
402
+ end
403
+
404
+ def test_no_duplicates_collection_global
405
+ hash = ActiveModelSerializers::SerializableResource.new(
406
+ [@nestedpost1, @nestedpost2],
407
+ adapter: :json_api,
408
+ include: '*'
409
+ ).serializable_hash
410
+ assert_nil(hash[:included])
411
+ end
412
+ end
413
+ end
414
+ end
415
+ end
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ module ActiveModelSerializers
6
+ module Adapter
7
+ class JsonApi
8
+ class LinksTest < ActiveSupport::TestCase
9
+ class LinkAuthor < ::Model; associations :posts end
10
+ class LinkAuthorSerializer < ActiveModel::Serializer
11
+ link :self do
12
+ href "http://example.com/link_author/#{object.id}"
13
+ meta stuff: 'value'
14
+ end
15
+ link(:author) { link_author_url(object.id) }
16
+ link(:link_authors) { url_for(controller: 'link_authors', action: 'index', only_path: false) }
17
+ link(:posts) { link_author_posts_url(object.id) }
18
+ link :resource, 'http://example.com/resource'
19
+ link :yet_another do
20
+ "http://example.com/resource/#{object.id}"
21
+ end
22
+ link :conditional1, if: -> { instance_truth } do
23
+ "http://example.com/conditional1/#{object.id}"
24
+ end
25
+ link :conditional2, if: :instance_falsey do
26
+ "http://example.com/conditional2/#{object.id}"
27
+ end
28
+ link(:nil) { nil }
29
+
30
+ def instance_truth
31
+ true
32
+ end
33
+
34
+ def instance_falsey
35
+ false
36
+ end
37
+ end
38
+
39
+ def setup
40
+ Rails.application.routes.draw do
41
+ resources :link_authors do
42
+ resources :posts
43
+ end
44
+ end
45
+ @post = Post.new(id: 1337, comments: [], author: nil)
46
+ @author = LinkAuthor.new(id: 1337, posts: [@post])
47
+ end
48
+
49
+ def test_toplevel_links
50
+ hash = ActiveModelSerializers::SerializableResource.new(
51
+ @post,
52
+ adapter: :json_api,
53
+ links: {
54
+ self: {
55
+ href: 'http://example.com/posts',
56
+ meta: {
57
+ stuff: 'value'
58
+ }
59
+ }
60
+ }
61
+ ).serializable_hash
62
+ expected = {
63
+ self: {
64
+ href: 'http://example.com/posts',
65
+ meta: {
66
+ stuff: 'value'
67
+ }
68
+ }
69
+ }
70
+ assert_equal(expected, hash[:links])
71
+ end
72
+
73
+ def test_nil_toplevel_links
74
+ hash = ActiveModelSerializers::SerializableResource.new(
75
+ @post,
76
+ adapter: :json_api,
77
+ links: nil
78
+ ).serializable_hash
79
+ refute hash.key?(:links), 'No links key to be output'
80
+ end
81
+
82
+ def test_nil_toplevel_links_json_adapter
83
+ hash = ActiveModelSerializers::SerializableResource.new(
84
+ @post,
85
+ adapter: :json,
86
+ links: nil
87
+ ).serializable_hash
88
+ refute hash.key?(:links), 'No links key to be output'
89
+ end
90
+
91
+ def test_resource_links
92
+ hash = serializable(@author, adapter: :json_api).serializable_hash
93
+ expected = {
94
+ self: {
95
+ href: 'http://example.com/link_author/1337',
96
+ meta: {
97
+ stuff: 'value'
98
+ }
99
+ },
100
+ author: 'http://example.com/link_authors/1337',
101
+ :"link-authors" => 'http://example.com/link_authors',
102
+ resource: 'http://example.com/resource',
103
+ posts: 'http://example.com/link_authors/1337/posts',
104
+ :"yet-another" => 'http://example.com/resource/1337',
105
+ conditional1: 'http://example.com/conditional1/1337'
106
+ }
107
+ assert_equal(expected, hash[:data][:links])
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end