active_model_serializers 0.10.0 → 0.10.7

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 (171) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +6 -5
  3. data/.travis.yml +30 -21
  4. data/CHANGELOG.md +172 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +23 -4
  7. data/README.md +166 -28
  8. data/Rakefile +3 -32
  9. data/active_model_serializers.gemspec +22 -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 +125 -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 +13 -3
  34. data/lib/active_model/serializer/adapter/base.rb +2 -0
  35. data/lib/active_model/serializer/array_serializer.rb +8 -5
  36. data/lib/active_model/serializer/association.rb +62 -10
  37. data/lib/active_model/serializer/belongs_to_reflection.rb +4 -3
  38. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  39. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +82 -115
  40. data/lib/active_model/serializer/error_serializer.rb +11 -7
  41. data/lib/active_model/serializer/errors_serializer.rb +25 -20
  42. data/lib/active_model/serializer/has_many_reflection.rb +3 -3
  43. data/lib/active_model/serializer/has_one_reflection.rb +1 -4
  44. data/lib/active_model/serializer/lazy_association.rb +95 -0
  45. data/lib/active_model/serializer/lint.rb +134 -130
  46. data/lib/active_model/serializer/reflection.rb +127 -67
  47. data/lib/active_model/serializer/version.rb +1 -1
  48. data/lib/active_model/serializer.rb +297 -79
  49. data/lib/active_model_serializers/adapter/attributes.rb +3 -66
  50. data/lib/active_model_serializers/adapter/base.rb +39 -39
  51. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +2 -2
  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 +47 -21
  54. data/lib/active_model_serializers/adapter/json_api/relationship.rb +75 -23
  55. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +39 -10
  56. data/lib/active_model_serializers/adapter/json_api.rb +71 -57
  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/lookup_chain.rb +80 -0
  61. data/lib/active_model_serializers/model.rb +109 -28
  62. data/lib/active_model_serializers/railtie.rb +3 -1
  63. data/lib/active_model_serializers/register_jsonapi_renderer.rb +44 -31
  64. data/lib/active_model_serializers/serializable_resource.rb +6 -5
  65. data/lib/active_model_serializers/serialization_context.rb +10 -3
  66. data/lib/active_model_serializers/test/schema.rb +2 -2
  67. data/lib/active_model_serializers.rb +16 -1
  68. data/lib/generators/rails/resource_override.rb +1 -1
  69. data/lib/generators/rails/serializer_generator.rb +4 -4
  70. data/lib/grape/active_model_serializers.rb +7 -5
  71. data/lib/grape/formatters/active_model_serializers.rb +19 -2
  72. data/lib/grape/helpers/active_model_serializers.rb +1 -0
  73. data/lib/tasks/rubocop.rake +53 -0
  74. data/test/action_controller/adapter_selector_test.rb +14 -5
  75. data/test/action_controller/explicit_serializer_test.rb +5 -4
  76. data/test/action_controller/json/include_test.rb +106 -27
  77. data/test/action_controller/json_api/deserialization_test.rb +1 -1
  78. data/test/action_controller/json_api/errors_test.rb +8 -9
  79. data/test/action_controller/json_api/fields_test.rb +66 -0
  80. data/test/action_controller/json_api/linked_test.rb +29 -24
  81. data/test/action_controller/json_api/pagination_test.rb +31 -23
  82. data/test/action_controller/json_api/transform_test.rb +11 -3
  83. data/test/action_controller/lookup_proc_test.rb +49 -0
  84. data/test/action_controller/namespace_lookup_test.rb +232 -0
  85. data/test/action_controller/serialization_scope_name_test.rb +12 -6
  86. data/test/action_controller/serialization_test.rb +12 -9
  87. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  88. data/test/active_model_serializers/model_test.rb +137 -4
  89. data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
  90. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  91. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  92. data/test/active_model_serializers/test/schema_test.rb +3 -2
  93. data/test/adapter/attributes_test.rb +40 -0
  94. data/test/adapter/json/collection_test.rb +14 -0
  95. data/test/adapter/json/has_many_test.rb +10 -2
  96. data/test/adapter/json/transform_test.rb +15 -15
  97. data/test/adapter/json_api/collection_test.rb +4 -3
  98. data/test/adapter/json_api/errors_test.rb +17 -19
  99. data/test/adapter/json_api/fields_test.rb +12 -3
  100. data/test/adapter/json_api/has_many_test.rb +49 -20
  101. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +213 -0
  102. data/test/adapter/json_api/json_api_test.rb +5 -7
  103. data/test/adapter/json_api/linked_test.rb +33 -12
  104. data/test/adapter/json_api/links_test.rb +4 -2
  105. data/test/adapter/json_api/pagination_links_test.rb +53 -13
  106. data/test/adapter/json_api/parse_test.rb +1 -1
  107. data/test/adapter/json_api/relationship_test.rb +309 -73
  108. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  109. data/test/adapter/json_api/transform_test.rb +263 -253
  110. data/test/adapter/json_api/type_test.rb +168 -36
  111. data/test/adapter/json_test.rb +8 -7
  112. data/test/adapter/null_test.rb +1 -2
  113. data/test/adapter/polymorphic_test.rb +52 -5
  114. data/test/adapter_test.rb +1 -1
  115. data/test/benchmark/app.rb +1 -1
  116. data/test/benchmark/benchmarking_support.rb +1 -1
  117. data/test/benchmark/bm_active_record.rb +81 -0
  118. data/test/benchmark/bm_adapter.rb +38 -0
  119. data/test/benchmark/bm_caching.rb +16 -16
  120. data/test/benchmark/bm_lookup_chain.rb +83 -0
  121. data/test/benchmark/bm_transform.rb +21 -10
  122. data/test/benchmark/controllers.rb +16 -17
  123. data/test/benchmark/fixtures.rb +72 -72
  124. data/test/cache_test.rb +235 -69
  125. data/test/collection_serializer_test.rb +31 -14
  126. data/test/fixtures/active_record.rb +45 -10
  127. data/test/fixtures/poro.rb +124 -181
  128. data/test/generators/serializer_generator_test.rb +23 -5
  129. data/test/grape_test.rb +170 -56
  130. data/test/lint_test.rb +1 -1
  131. data/test/logger_test.rb +13 -11
  132. data/test/serializable_resource_test.rb +18 -22
  133. data/test/serializers/association_macros_test.rb +3 -2
  134. data/test/serializers/associations_test.rb +222 -49
  135. data/test/serializers/attribute_test.rb +5 -3
  136. data/test/serializers/attributes_test.rb +1 -1
  137. data/test/serializers/caching_configuration_test_isolated.rb +6 -6
  138. data/test/serializers/fieldset_test.rb +1 -1
  139. data/test/serializers/meta_test.rb +12 -6
  140. data/test/serializers/options_test.rb +17 -6
  141. data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
  142. data/test/serializers/reflection_test.rb +427 -0
  143. data/test/serializers/root_test.rb +1 -1
  144. data/test/serializers/serialization_test.rb +2 -2
  145. data/test/serializers/serializer_for_test.rb +12 -10
  146. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  147. data/test/support/isolated_unit.rb +9 -4
  148. data/test/support/rails5_shims.rb +8 -2
  149. data/test/support/rails_app.rb +2 -9
  150. data/test/support/serialization_testing.rb +31 -5
  151. data/test/test_helper.rb +13 -0
  152. metadata +130 -71
  153. data/.rubocop_todo.yml +0 -167
  154. data/docs/ARCHITECTURE.md +0 -126
  155. data/lib/active_model/serializer/associations.rb +0 -100
  156. data/lib/active_model/serializer/attributes.rb +0 -82
  157. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  158. data/lib/active_model/serializer/configuration.rb +0 -35
  159. data/lib/active_model/serializer/include_tree.rb +0 -111
  160. data/lib/active_model/serializer/links.rb +0 -35
  161. data/lib/active_model/serializer/meta.rb +0 -29
  162. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  163. data/lib/active_model/serializer/type.rb +0 -25
  164. data/lib/active_model_serializers/key_transform.rb +0 -70
  165. data/test/active_model_serializers/key_transform_test.rb +0 -263
  166. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  167. data/test/adapter/json_api/relationships_test.rb +0 -199
  168. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  169. data/test/include_tree/from_include_args_test.rb +0 -26
  170. data/test/include_tree/from_string_test.rb +0 -94
  171. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -0,0 +1,213 @@
1
+ require 'test_helper'
2
+
3
+ module ActiveModel
4
+ class Serializer
5
+ module Adapter
6
+ class JsonApi
7
+ class IncludeParamTest < ActiveSupport::TestCase
8
+ IncludeParamAuthor = Class.new(::Model) do
9
+ associations :tags, :posts, :roles
10
+ end
11
+
12
+ class CustomCommentLoader
13
+ def all
14
+ [{ foo: 'bar' }]
15
+ end
16
+ end
17
+ class Tag < ::Model
18
+ attributes :id, :name
19
+ end
20
+
21
+ class TagSerializer < ActiveModel::Serializer
22
+ type 'tags'
23
+ attributes :id, :name
24
+ end
25
+
26
+ class PostWithTagsSerializer < ActiveModel::Serializer
27
+ type 'posts'
28
+ attributes :id
29
+ has_many :tags
30
+ end
31
+
32
+ class IncludeParamAuthorSerializer < ActiveModel::Serializer
33
+ class_attribute :comment_loader
34
+
35
+ has_many :tags, serializer: TagSerializer do
36
+ link :self, '//example.com/link_author/relationships/tags'
37
+ include_data :if_sideloaded
38
+ end
39
+
40
+ has_many :unlinked_tags, serializer: TagSerializer do
41
+ include_data :if_sideloaded
42
+ end
43
+
44
+ has_many :posts, serializer: PostWithTagsSerializer do
45
+ include_data :if_sideloaded
46
+ end
47
+ has_many :locations do
48
+ include_data :if_sideloaded
49
+ end
50
+ has_many :comments do
51
+ include_data :if_sideloaded
52
+ IncludeParamAuthorSerializer.comment_loader.all
53
+ end
54
+ has_many :roles, key: :granted_roles do
55
+ include_data :if_sideloaded
56
+ end
57
+ end
58
+
59
+ def setup
60
+ IncludeParamAuthorSerializer.comment_loader = Class.new(CustomCommentLoader).new
61
+ @tag = Tag.new(id: 1337, name: 'mytag')
62
+ @role = Role.new(id: 1337, name: 'myrole')
63
+ @author = IncludeParamAuthor.new(
64
+ id: 1337,
65
+ tags: [@tag],
66
+ roles: [@role]
67
+ )
68
+ end
69
+
70
+ def test_relationship_not_loaded_when_not_included
71
+ expected = {
72
+ links: {
73
+ self: '//example.com/link_author/relationships/tags'
74
+ }
75
+ }
76
+
77
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
78
+ fail 'should not be called' if attr == :tags
79
+ super(attr)
80
+ end
81
+
82
+ assert_relationship(:tags, expected)
83
+ end
84
+
85
+ def test_relationship_included
86
+ expected = {
87
+ data: [
88
+ {
89
+ id: '1337',
90
+ type: 'tags'
91
+ }
92
+ ],
93
+ links: {
94
+ self: '//example.com/link_author/relationships/tags'
95
+ }
96
+ }
97
+
98
+ assert_relationship(:tags, expected, include: :tags)
99
+ end
100
+
101
+ def test_sideloads_included
102
+ expected = [
103
+ {
104
+ id: '1337',
105
+ type: 'tags',
106
+ attributes: { name: 'mytag' }
107
+ }
108
+ ]
109
+ hash = result(include: :tags)
110
+ assert_equal(expected, hash[:included])
111
+ end
112
+
113
+ def test_sideloads_included_when_using_key
114
+ expected = [
115
+ {
116
+ id: '1337',
117
+ type: 'roles',
118
+ attributes: {
119
+ name: 'myrole',
120
+ description: nil,
121
+ slug: 'myrole-1337'
122
+ },
123
+ relationships: {
124
+ author: { data: nil }
125
+ }
126
+ }
127
+ ]
128
+
129
+ hash = result(include: :granted_roles)
130
+ assert_equal(expected, hash[:included])
131
+ end
132
+
133
+ def test_sideloads_not_included_when_using_name_when_key_defined
134
+ hash = result(include: :roles)
135
+ assert_nil(hash[:included])
136
+ end
137
+
138
+ def test_nested_relationship
139
+ expected = {
140
+ data: [
141
+ {
142
+ id: '1337',
143
+ type: 'tags'
144
+ }
145
+ ],
146
+ links: {
147
+ self: '//example.com/link_author/relationships/tags'
148
+ }
149
+ }
150
+
151
+ expected_no_data = {
152
+ links: {
153
+ self: '//example.com/link_author/relationships/tags'
154
+ }
155
+ }
156
+
157
+ assert_relationship(:tags, expected, include: [:tags, { posts: :tags }])
158
+
159
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
160
+ fail 'should not be called' if attr == :tags
161
+ super(attr)
162
+ end
163
+
164
+ assert_relationship(:tags, expected_no_data, include: { posts: :tags })
165
+ end
166
+
167
+ def test_include_params_with_no_block
168
+ @author.define_singleton_method(:read_attribute_for_serialization) do |attr|
169
+ fail 'should not be called' if attr == :locations
170
+ super(attr)
171
+ end
172
+
173
+ expected = { meta: {} }
174
+
175
+ assert_relationship(:locations, expected)
176
+ end
177
+
178
+ def test_block_relationship
179
+ expected = {
180
+ data: [
181
+ { 'foo' => 'bar' }
182
+ ]
183
+ }
184
+
185
+ assert_relationship(:comments, expected, include: [:comments])
186
+ end
187
+
188
+ def test_node_not_included_when_no_link
189
+ expected = { meta: {} }
190
+ assert_relationship(:unlinked_tags, expected, key_transform: :unaltered)
191
+ end
192
+
193
+ private
194
+
195
+ def assert_relationship(relationship_name, expected, opts = {})
196
+ actual = relationship_data(relationship_name, opts)
197
+ assert_equal(expected, actual)
198
+ end
199
+
200
+ def result(opts)
201
+ opts = { adapter: :json_api }.merge(opts)
202
+ serializable(@author, opts).serializable_hash
203
+ end
204
+
205
+ def relationship_data(relationship_name, opts = {})
206
+ hash = result(opts)
207
+ hash[:data][:relationships][relationship_name]
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
@@ -22,13 +22,11 @@ module ActiveModelSerializers
22
22
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
23
23
 
24
24
  assert_equal({
25
- reviews: { data: [
26
- { type: 'comments', id: '1' },
27
- { type: 'comments', id: '2' }
28
- ] },
29
- writer: { data: { type: 'authors', id: '1' } },
30
- site: { data: { type: 'blogs', id: '1' } }
31
- }, adapter.serializable_hash[:data][:relationships])
25
+ reviews: { data: [{ type: 'comments', id: '1' },
26
+ { type: 'comments', id: '2' }] },
27
+ writer: { data: { type: 'authors', id: '1' } },
28
+ site: { data: { type: 'blogs', id: '1' } }
29
+ }, adapter.serializable_hash[:data][:relationships])
32
30
  end
33
31
  end
34
32
  end
@@ -1,10 +1,9 @@
1
1
  require 'test_helper'
2
2
 
3
- NestedPost = Class.new(Model)
3
+ class NestedPost < ::Model; associations :nested_posts end
4
4
  class NestedPostSerializer < ActiveModel::Serializer
5
5
  has_many :nested_posts
6
6
  end
7
-
8
7
  module ActiveModelSerializers
9
8
  module Adapter
10
9
  class JsonApi
@@ -17,7 +16,7 @@ module ActiveModelSerializers
17
16
  @first_post = Post.new(id: 10, title: 'Hello!!', body: 'Hello, world!!')
18
17
  @second_post = Post.new(id: 20, title: 'New Post', body: 'Body')
19
18
  @third_post = Post.new(id: 30, title: 'Yet Another Post', body: 'Body')
20
- @blog = Blog.new({ name: 'AMS Blog' })
19
+ @blog = Blog.new(name: 'AMS Blog')
21
20
  @first_comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
22
21
  @second_comment = Comment.new(id: 2, body: 'ZOMG ANOTHER COMMENT')
23
22
  @first_post.blog = @blog
@@ -224,6 +223,25 @@ module ActiveModelSerializers
224
223
  assert_equal expected, relationships
225
224
  end
226
225
 
226
+ def test_underscore_model_namespace_with_namespace_separator_for_linked_resource_type
227
+ spammy_post = Post.new(id: 123)
228
+ spammy_post.related = [Spam::UnrelatedLink.new(id: 456)]
229
+ serializer = SpammyPostSerializer.new(spammy_post)
230
+ adapter = ActiveModelSerializers::Adapter::JsonApi.new(serializer)
231
+ relationships = with_namespace_separator '--' do
232
+ adapter.serializable_hash[:data][:relationships]
233
+ end
234
+ expected = {
235
+ related: {
236
+ data: [{
237
+ type: 'spam--unrelated-links',
238
+ id: '456'
239
+ }]
240
+ }
241
+ }
242
+ assert_equal expected, relationships
243
+ end
244
+
227
245
  def test_multiple_references_to_same_resource
228
246
  serializer = ActiveModel::Serializer::CollectionSerializer.new([@first_comment, @second_comment])
229
247
  adapter = ActiveModelSerializers::Adapter::JsonApi.new(
@@ -283,8 +301,8 @@ module ActiveModelSerializers
283
301
  end
284
302
 
285
303
  class NoDuplicatesTest < ActiveSupport::TestCase
286
- Post = Class.new(::Model)
287
- Author = Class.new(::Model)
304
+ class Post < ::Model; associations :author end
305
+ class Author < ::Model; associations :posts, :roles, :bio end
288
306
 
289
307
  class PostSerializer < ActiveModel::Serializer
290
308
  type 'posts'
@@ -303,8 +321,8 @@ module ActiveModelSerializers
303
321
  @author.posts << @post1
304
322
  @author.posts << @post2
305
323
 
306
- @nestedpost1 = ::NestedPost.new(id: 1, nested_posts: [])
307
- @nestedpost2 = ::NestedPost.new(id: 2, nested_posts: [])
324
+ @nestedpost1 = NestedPost.new(id: 1, nested_posts: [])
325
+ @nestedpost2 = NestedPost.new(id: 2, nested_posts: [])
308
326
  @nestedpost1.nested_posts << @nestedpost1
309
327
  @nestedpost1.nested_posts << @nestedpost2
310
328
  @nestedpost2.nested_posts << @nestedpost1
@@ -341,9 +359,10 @@ module ActiveModelSerializers
341
359
 
342
360
  def test_no_duplicates_collection
343
361
  hash = ActiveModelSerializers::SerializableResource.new(
344
- [@post1, @post2], adapter: :json_api,
345
- include: '*.*')
346
- .serializable_hash
362
+ [@post1, @post2],
363
+ adapter: :json_api,
364
+ include: '*.*'
365
+ ).serializable_hash
347
366
  expected = [
348
367
  {
349
368
  type: 'authors', id: '1',
@@ -364,7 +383,8 @@ module ActiveModelSerializers
364
383
  hash = ActiveModelSerializers::SerializableResource.new(
365
384
  @nestedpost1,
366
385
  adapter: :json_api,
367
- include: '*').serializable_hash
386
+ include: '*'
387
+ ).serializable_hash
368
388
  expected = [
369
389
  type: 'nested-posts', id: '2',
370
390
  relationships: {
@@ -383,7 +403,8 @@ module ActiveModelSerializers
383
403
  hash = ActiveModelSerializers::SerializableResource.new(
384
404
  [@nestedpost1, @nestedpost2],
385
405
  adapter: :json_api,
386
- include: '*').serializable_hash
406
+ include: '*'
407
+ ).serializable_hash
387
408
  assert_nil(hash[:included])
388
409
  end
389
410
  end
@@ -4,7 +4,7 @@ module ActiveModelSerializers
4
4
  module Adapter
5
5
  class JsonApi
6
6
  class LinksTest < ActiveSupport::TestCase
7
- LinkAuthor = Class.new(::Model)
7
+ class LinkAuthor < ::Model; associations :posts end
8
8
  class LinkAuthorSerializer < ActiveModel::Serializer
9
9
  link :self do
10
10
  href "http://example.com/link_author/#{object.id}"
@@ -17,6 +17,7 @@ module ActiveModelSerializers
17
17
  link :yet_another do
18
18
  "http://example.com/resource/#{object.id}"
19
19
  end
20
+ link(:nil) { nil }
20
21
  end
21
22
 
22
23
  def setup
@@ -40,7 +41,8 @@ module ActiveModelSerializers
40
41
  stuff: 'value'
41
42
  }
42
43
  }
43
- }).serializable_hash
44
+ }
45
+ ).serializable_hash
44
46
  expected = {
45
47
  self: {
46
48
  href: 'http://example.com/posts',
@@ -13,11 +13,11 @@ module ActiveModelSerializers
13
13
  def setup
14
14
  ActionController::Base.cache_store.clear
15
15
  @array = [
16
- Profile.new({ id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }),
17
- Profile.new({ id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2' }),
18
- Profile.new({ id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3' }),
19
- Profile.new({ id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4' }),
20
- Profile.new({ id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5' })
16
+ Profile.new(id: 1, name: 'Name 1', description: 'Description 1', comments: 'Comments 1'),
17
+ Profile.new(id: 2, name: 'Name 2', description: 'Description 2', comments: 'Comments 2'),
18
+ Profile.new(id: 3, name: 'Name 3', description: 'Description 3', comments: 'Comments 3'),
19
+ Profile.new(id: 4, name: 'Name 4', description: 'Description 4', comments: 'Comments 4'),
20
+ Profile.new(id: 5, name: 'Name 5', description: 'Description 5', comments: 'Comments 5')
21
21
  ]
22
22
  end
23
23
 
@@ -43,7 +43,8 @@ module ActiveModelSerializers
43
43
  end
44
44
 
45
45
  def data
46
- { data: [
46
+ {
47
+ data: [
47
48
  { id: '1', type: 'profiles', attributes: { name: 'Name 1', description: 'Description 1' } },
48
49
  { id: '2', type: 'profiles', attributes: { name: 'Name 2', description: 'Description 2' } },
49
50
  { id: '3', type: 'profiles', attributes: { name: 'Name 3', description: 'Description 3' } },
@@ -53,6 +54,16 @@ module ActiveModelSerializers
53
54
  }
54
55
  end
55
56
 
57
+ def empty_collection_links
58
+ {
59
+ self: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
60
+ first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
61
+ prev: nil,
62
+ next: nil,
63
+ last: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2"
64
+ }
65
+ end
66
+
56
67
  def links
57
68
  {
58
69
  links: {
@@ -70,12 +81,14 @@ module ActiveModelSerializers
70
81
  links: {
71
82
  self: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2",
72
83
  first: "#{URI}?page%5Bnumber%5D=1&page%5Bsize%5D=2",
73
- prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2"
84
+ prev: "#{URI}?page%5Bnumber%5D=2&page%5Bsize%5D=2",
85
+ next: nil,
86
+ last: "#{URI}?page%5Bnumber%5D=3&page%5Bsize%5D=2"
74
87
  }
75
88
  }
76
89
  end
77
90
 
78
- def expected_response_without_pagination_links
91
+ def expected_response_when_unpaginatable
79
92
  data
80
93
  end
81
94
 
@@ -86,6 +99,12 @@ module ActiveModelSerializers
86
99
  end
87
100
  end
88
101
 
102
+ def expected_response_without_pagination_links
103
+ {}.tap do |hash|
104
+ hash[:data] = data.values.flatten[2..3]
105
+ end
106
+ end
107
+
89
108
  def expected_response_with_pagination_links_and_additional_params
90
109
  new_links = links[:links].each_with_object({}) { |(key, value), hash| hash[key] = "#{value}&test=test" }
91
110
  {}.tap do |hash|
@@ -101,10 +120,10 @@ module ActiveModelSerializers
101
120
  end
102
121
  end
103
122
 
104
- def expected_response_with_no_data_pagination_links
123
+ def expected_response_with_empty_collection_pagination_links
105
124
  {}.tap do |hash|
106
125
  hash[:data] = []
107
- hash[:links] = {}
126
+ hash.merge! links: empty_collection_links
108
127
  end
109
128
  end
110
129
 
@@ -121,7 +140,7 @@ module ActiveModelSerializers
121
140
  end
122
141
 
123
142
  def test_pagination_links_with_additional_params
124
- adapter = load_adapter(using_will_paginate, mock_request({ test: 'test' }))
143
+ adapter = load_adapter(using_will_paginate, mock_request(test: 'test'))
125
144
 
126
145
  assert_equal expected_response_with_pagination_links_and_additional_params,
127
146
  adapter.serializable_hash
@@ -132,7 +151,7 @@ module ActiveModelSerializers
132
151
 
133
152
  adapter = load_adapter(using_kaminari(1), mock_request)
134
153
 
135
- assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
154
+ assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
136
155
  end
137
156
 
138
157
  def test_pagination_links_when_zero_results_will_paginate
@@ -140,7 +159,7 @@ module ActiveModelSerializers
140
159
 
141
160
  adapter = load_adapter(using_will_paginate(1), mock_request)
142
161
 
143
- assert_equal expected_response_with_no_data_pagination_links, adapter.serializable_hash
162
+ assert_equal expected_response_with_empty_collection_pagination_links, adapter.serializable_hash
144
163
  end
145
164
 
146
165
  def test_last_page_pagination_links_using_kaminari
@@ -158,7 +177,28 @@ module ActiveModelSerializers
158
177
  def test_not_showing_pagination_links
159
178
  adapter = load_adapter(@array, mock_request)
160
179
 
180
+ assert_equal expected_response_when_unpaginatable, adapter.serializable_hash
181
+ end
182
+
183
+ def test_raises_descriptive_error_when_serialization_context_unset
184
+ render_options = { adapter: :json_api }
185
+ adapter = serializable(using_kaminari, render_options)
186
+ exception_class = ActiveModelSerializers::Adapter::JsonApi::PaginationLinks::MissingSerializationContextError
187
+
188
+ exception = assert_raises(exception_class) do
189
+ adapter.as_json
190
+ end
191
+ assert_equal exception_class, exception.class
192
+ assert_match(/CollectionSerializer#paginated\?/, exception.message)
193
+ end
194
+
195
+ def test_pagination_links_not_present_when_disabled
196
+ ActiveModel::Serializer.config.jsonapi_pagination_links_enabled = false
197
+ adapter = load_adapter(using_kaminari, mock_request)
198
+
161
199
  assert_equal expected_response_without_pagination_links, adapter.serializable_hash
200
+ ensure
201
+ ActiveModel::Serializer.config.jsonapi_pagination_links_enabled = true
162
202
  end
163
203
  end
164
204
  end
@@ -125,7 +125,7 @@ module ActiveModelSerializers
125
125
  src: 'http://example.com/images/productivity.png',
126
126
  author_id: nil,
127
127
  photographer_id: '9',
128
- photographer_type: 'people',
128
+ photographer_type: 'Person',
129
129
  comment_ids: %w(1 2)
130
130
  }
131
131
  assert_equal(expected, parsed_hash)