active_model_serializers 0.10.0 → 0.10.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +10 -5
  3. data/.travis.yml +41 -21
  4. data/CHANGELOG.md +200 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +25 -4
  7. data/README.md +166 -28
  8. data/Rakefile +5 -32
  9. data/active_model_serializers.gemspec +23 -25
  10. data/appveyor.yml +10 -6
  11. data/bin/rubocop +38 -0
  12. data/docs/README.md +2 -1
  13. data/docs/general/adapters.md +35 -11
  14. data/docs/general/caching.md +7 -1
  15. data/docs/general/configuration_options.md +86 -1
  16. data/docs/general/deserialization.md +1 -1
  17. data/docs/general/fields.md +31 -0
  18. data/docs/general/getting_started.md +1 -1
  19. data/docs/general/logging.md +7 -0
  20. data/docs/general/rendering.md +63 -25
  21. data/docs/general/serializers.md +137 -14
  22. data/docs/howto/add_pagination_links.md +16 -17
  23. data/docs/howto/add_relationship_links.md +140 -0
  24. data/docs/howto/add_root_key.md +11 -0
  25. data/docs/howto/grape_integration.md +42 -0
  26. data/docs/howto/outside_controller_use.md +12 -4
  27. data/docs/howto/passing_arbitrary_options.md +2 -2
  28. data/docs/howto/serialize_poro.md +46 -5
  29. data/docs/howto/test.md +2 -0
  30. data/docs/howto/upgrade_from_0_8_to_0_10.md +265 -0
  31. data/docs/integrations/ember-and-json-api.md +67 -32
  32. data/docs/jsonapi/schema.md +1 -1
  33. data/lib/action_controller/serialization.rb +15 -3
  34. data/lib/active_model/serializable_resource.rb +2 -0
  35. data/lib/active_model/serializer/adapter/attributes.rb +2 -0
  36. data/lib/active_model/serializer/adapter/base.rb +4 -0
  37. data/lib/active_model/serializer/adapter/json.rb +2 -0
  38. data/lib/active_model/serializer/adapter/json_api.rb +2 -0
  39. data/lib/active_model/serializer/adapter/null.rb +2 -0
  40. data/lib/active_model/serializer/adapter.rb +2 -0
  41. data/lib/active_model/serializer/array_serializer.rb +10 -5
  42. data/lib/active_model/serializer/association.rb +64 -10
  43. data/lib/active_model/serializer/attribute.rb +2 -0
  44. data/lib/active_model/serializer/belongs_to_reflection.rb +6 -3
  45. data/lib/active_model/serializer/collection_serializer.rb +39 -13
  46. data/lib/active_model/serializer/{caching.rb → concerns/caching.rb} +87 -116
  47. data/lib/active_model/serializer/error_serializer.rb +13 -7
  48. data/lib/active_model/serializer/errors_serializer.rb +27 -20
  49. data/lib/active_model/serializer/field.rb +2 -0
  50. data/lib/active_model/serializer/fieldset.rb +2 -0
  51. data/lib/active_model/serializer/has_many_reflection.rb +5 -3
  52. data/lib/active_model/serializer/has_one_reflection.rb +3 -4
  53. data/lib/active_model/serializer/lazy_association.rb +99 -0
  54. data/lib/active_model/serializer/link.rb +23 -0
  55. data/lib/active_model/serializer/lint.rb +136 -130
  56. data/lib/active_model/serializer/null.rb +2 -0
  57. data/lib/active_model/serializer/reflection.rb +132 -67
  58. data/lib/active_model/serializer/version.rb +3 -1
  59. data/lib/active_model/serializer.rb +308 -82
  60. data/lib/active_model_serializers/adapter/attributes.rb +5 -66
  61. data/lib/active_model_serializers/adapter/base.rb +41 -39
  62. data/lib/active_model_serializers/adapter/json.rb +2 -0
  63. data/lib/active_model_serializers/adapter/json_api/deserialization.rb +4 -2
  64. data/lib/active_model_serializers/adapter/json_api/error.rb +2 -0
  65. data/lib/active_model_serializers/adapter/json_api/jsonapi.rb +2 -0
  66. data/lib/active_model_serializers/adapter/json_api/link.rb +3 -1
  67. data/lib/active_model_serializers/adapter/json_api/meta.rb +2 -0
  68. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +49 -21
  69. data/lib/active_model_serializers/adapter/json_api/relationship.rb +77 -23
  70. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +41 -10
  71. data/lib/active_model_serializers/adapter/json_api.rb +84 -65
  72. data/lib/active_model_serializers/adapter/null.rb +2 -0
  73. data/lib/active_model_serializers/adapter.rb +9 -1
  74. data/lib/active_model_serializers/callbacks.rb +2 -0
  75. data/lib/active_model_serializers/deprecate.rb +3 -2
  76. data/lib/active_model_serializers/deserialization.rb +4 -0
  77. data/lib/active_model_serializers/json_pointer.rb +2 -0
  78. data/lib/active_model_serializers/logging.rb +2 -0
  79. data/lib/active_model_serializers/lookup_chain.rb +82 -0
  80. data/lib/active_model_serializers/model.rb +111 -28
  81. data/lib/active_model_serializers/railtie.rb +7 -1
  82. data/lib/active_model_serializers/register_jsonapi_renderer.rb +46 -31
  83. data/lib/active_model_serializers/serializable_resource.rb +10 -7
  84. data/lib/active_model_serializers/serialization_context.rb +12 -3
  85. data/lib/active_model_serializers/test/schema.rb +4 -2
  86. data/lib/active_model_serializers/test/serializer.rb +2 -0
  87. data/lib/active_model_serializers/test.rb +2 -0
  88. data/lib/active_model_serializers.rb +35 -10
  89. data/lib/generators/rails/resource_override.rb +3 -1
  90. data/lib/generators/rails/serializer_generator.rb +6 -4
  91. data/lib/grape/active_model_serializers.rb +9 -5
  92. data/lib/grape/formatters/active_model_serializers.rb +21 -2
  93. data/lib/grape/helpers/active_model_serializers.rb +3 -0
  94. data/lib/tasks/rubocop.rake +55 -0
  95. data/test/action_controller/adapter_selector_test.rb +16 -5
  96. data/test/action_controller/explicit_serializer_test.rb +7 -4
  97. data/test/action_controller/json/include_test.rb +108 -27
  98. data/test/action_controller/json_api/deserialization_test.rb +3 -1
  99. data/test/action_controller/json_api/errors_test.rb +10 -9
  100. data/test/action_controller/json_api/fields_test.rb +68 -0
  101. data/test/action_controller/json_api/linked_test.rb +31 -24
  102. data/test/action_controller/json_api/pagination_test.rb +33 -23
  103. data/test/action_controller/json_api/transform_test.rb +13 -3
  104. data/test/action_controller/lookup_proc_test.rb +51 -0
  105. data/test/action_controller/namespace_lookup_test.rb +234 -0
  106. data/test/action_controller/serialization_scope_name_test.rb +14 -6
  107. data/test/action_controller/serialization_test.rb +23 -12
  108. data/test/active_model_serializers/adapter_for_test.rb +2 -0
  109. data/test/active_model_serializers/json_pointer_test.rb +17 -13
  110. data/test/active_model_serializers/logging_test.rb +2 -0
  111. data/test/active_model_serializers/model_test.rb +139 -4
  112. data/test/active_model_serializers/railtie_test_isolated.rb +14 -7
  113. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +163 -0
  114. data/test/active_model_serializers/serialization_context_test_isolated.rb +25 -10
  115. data/test/active_model_serializers/test/schema_test.rb +5 -2
  116. data/test/active_model_serializers/test/serializer_test.rb +2 -0
  117. data/test/active_record_test.rb +2 -0
  118. data/test/adapter/attributes_test.rb +42 -0
  119. data/test/adapter/deprecation_test.rb +2 -0
  120. data/test/adapter/json/belongs_to_test.rb +2 -0
  121. data/test/adapter/json/collection_test.rb +16 -0
  122. data/test/adapter/json/has_many_test.rb +12 -2
  123. data/test/adapter/json/transform_test.rb +17 -15
  124. data/test/adapter/json_api/belongs_to_test.rb +2 -0
  125. data/test/adapter/json_api/collection_test.rb +6 -3
  126. data/test/adapter/json_api/errors_test.rb +19 -19
  127. data/test/adapter/json_api/fields_test.rb +14 -3
  128. data/test/adapter/json_api/has_many_explicit_serializer_test.rb +2 -0
  129. data/test/adapter/json_api/has_many_test.rb +51 -20
  130. data/test/adapter/json_api/has_one_test.rb +2 -0
  131. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +215 -0
  132. data/test/adapter/json_api/json_api_test.rb +7 -7
  133. data/test/adapter/json_api/linked_test.rb +35 -12
  134. data/test/adapter/json_api/links_test.rb +22 -3
  135. data/test/adapter/json_api/pagination_links_test.rb +55 -13
  136. data/test/adapter/json_api/parse_test.rb +3 -1
  137. data/test/adapter/json_api/relationship_test.rb +311 -73
  138. data/test/adapter/json_api/resource_meta_test.rb +5 -3
  139. data/test/adapter/json_api/toplevel_jsonapi_test.rb +2 -0
  140. data/test/adapter/json_api/transform_test.rb +265 -253
  141. data/test/adapter/json_api/type_test.rb +170 -36
  142. data/test/adapter/json_test.rb +10 -7
  143. data/test/adapter/null_test.rb +3 -2
  144. data/test/adapter/polymorphic_test.rb +54 -5
  145. data/test/adapter_test.rb +3 -1
  146. data/test/array_serializer_test.rb +2 -0
  147. data/test/benchmark/app.rb +3 -1
  148. data/test/benchmark/benchmarking_support.rb +3 -1
  149. data/test/benchmark/bm_active_record.rb +83 -0
  150. data/test/benchmark/bm_adapter.rb +40 -0
  151. data/test/benchmark/bm_caching.rb +18 -16
  152. data/test/benchmark/bm_lookup_chain.rb +85 -0
  153. data/test/benchmark/bm_transform.rb +23 -10
  154. data/test/benchmark/controllers.rb +18 -17
  155. data/test/benchmark/fixtures.rb +74 -72
  156. data/test/cache_test.rb +301 -69
  157. data/test/collection_serializer_test.rb +33 -14
  158. data/test/fixtures/active_record.rb +47 -10
  159. data/test/fixtures/poro.rb +128 -183
  160. data/test/generators/scaffold_controller_generator_test.rb +2 -0
  161. data/test/generators/serializer_generator_test.rb +25 -5
  162. data/test/grape_test.rb +172 -56
  163. data/test/lint_test.rb +3 -1
  164. data/test/logger_test.rb +15 -11
  165. data/test/poro_test.rb +2 -0
  166. data/test/serializable_resource_test.rb +20 -22
  167. data/test/serializers/association_macros_test.rb +5 -2
  168. data/test/serializers/associations_test.rb +274 -49
  169. data/test/serializers/attribute_test.rb +7 -3
  170. data/test/serializers/attributes_test.rb +3 -1
  171. data/test/serializers/caching_configuration_test_isolated.rb +8 -6
  172. data/test/serializers/configuration_test.rb +2 -0
  173. data/test/serializers/fieldset_test.rb +3 -1
  174. data/test/serializers/meta_test.rb +14 -6
  175. data/test/serializers/options_test.rb +19 -6
  176. data/test/serializers/read_attribute_for_serialization_test.rb +5 -3
  177. data/test/serializers/reflection_test.rb +481 -0
  178. data/test/serializers/root_test.rb +3 -1
  179. data/test/serializers/serialization_test.rb +4 -2
  180. data/test/serializers/serializer_for_test.rb +14 -10
  181. data/test/serializers/serializer_for_with_namespace_test.rb +90 -0
  182. data/test/support/isolated_unit.rb +11 -4
  183. data/test/support/rails5_shims.rb +10 -2
  184. data/test/support/rails_app.rb +4 -9
  185. data/test/support/serialization_testing.rb +33 -5
  186. data/test/test_helper.rb +15 -0
  187. metadata +126 -46
  188. data/.rubocop_todo.yml +0 -167
  189. data/docs/ARCHITECTURE.md +0 -126
  190. data/lib/active_model/serializer/associations.rb +0 -100
  191. data/lib/active_model/serializer/attributes.rb +0 -82
  192. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  193. data/lib/active_model/serializer/configuration.rb +0 -35
  194. data/lib/active_model/serializer/include_tree.rb +0 -111
  195. data/lib/active_model/serializer/links.rb +0 -35
  196. data/lib/active_model/serializer/meta.rb +0 -29
  197. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  198. data/lib/active_model/serializer/type.rb +0 -25
  199. data/lib/active_model_serializers/key_transform.rb +0 -70
  200. data/test/active_model_serializers/key_transform_test.rb +0 -263
  201. data/test/adapter/json_api/has_many_embed_ids_test.rb +0 -43
  202. data/test/adapter/json_api/relationships_test.rb +0 -199
  203. data/test/adapter/json_api/resource_identifier_test.rb +0 -85
  204. data/test/include_tree/from_include_args_test.rb +0 -26
  205. data/test/include_tree/from_string_test.rb +0 -94
  206. data/test/include_tree/include_args_to_hash_test.rb +0 -64
@@ -1,16 +1,21 @@
1
- require 'test_helper'
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'test_helper'
3
4
  module ActiveModel
4
5
  class Serializer
5
6
  class AssociationsTest < ActiveSupport::TestCase
7
+ class ModelWithoutSerializer < ::Model
8
+ attributes :id, :name
9
+ end
10
+
6
11
  def setup
7
12
  @author = Author.new(name: 'Steve K.')
8
13
  @author.bio = nil
9
14
  @author.roles = []
10
- @blog = Blog.new({ name: 'AMS Blog' })
11
- @post = Post.new({ title: 'New Post', body: 'Body' })
12
- @tag = Tag.new({ name: '#hashtagged' })
13
- @comment = Comment.new({ id: 1, body: 'ZOMG A COMMENT' })
15
+ @blog = Blog.new(name: 'AMS Blog')
16
+ @post = Post.new(title: 'New Post', body: 'Body')
17
+ @tag = ModelWithoutSerializer.new(id: 'tagid', name: '#hashtagged')
18
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
14
19
  @post.comments = [@comment]
15
20
  @post.tags = [@tag]
16
21
  @post.blog = @blog
@@ -19,7 +24,7 @@ module ActiveModel
19
24
  @post.author = @author
20
25
  @author.posts = [@post]
21
26
 
22
- @post_serializer = PostSerializer.new(@post, { custom_options: true })
27
+ @post_serializer = PostSerializer.new(@post, custom_options: true)
23
28
  @author_serializer = AuthorSerializer.new(@author)
24
29
  @comment_serializer = CommentSerializer.new(@comment)
25
30
  end
@@ -27,18 +32,17 @@ module ActiveModel
27
32
  def test_has_many_and_has_one
28
33
  @author_serializer.associations.each do |association|
29
34
  key = association.key
30
- serializer = association.serializer
31
- options = association.options
35
+ serializer = association.lazy_association.serializer
32
36
 
33
37
  case key
34
38
  when :posts
35
- assert_equal({ include_data: true }, options)
39
+ assert_equal true, association.include_data?
36
40
  assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
37
41
  when :bio
38
- assert_equal({ include_data: true }, options)
42
+ assert_equal true, association.include_data?
39
43
  assert_nil serializer
40
44
  when :roles
41
- assert_equal({ include_data: true }, options)
45
+ assert_equal true, association.include_data?
42
46
  assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
43
47
  else
44
48
  flunk "Unknown association: #{key}"
@@ -47,14 +51,17 @@ module ActiveModel
47
51
  end
48
52
 
49
53
  def test_has_many_with_no_serializer
50
- PostWithTagsSerializer.new(@post).associations.each do |association|
54
+ post_serializer_class = Class.new(ActiveModel::Serializer) do
55
+ attributes :id
56
+ has_many :tags
57
+ end
58
+ post_serializer_class.new(@post).associations.each do |association|
51
59
  key = association.key
52
- serializer = association.serializer
53
- options = association.options
60
+ serializer = association.lazy_association.serializer
54
61
 
55
62
  assert_equal :tags, key
56
63
  assert_nil serializer
57
- assert_equal [{ name: '#hashtagged' }].to_json, options[:virtual_value].to_json
64
+ assert_equal [{ id: 'tagid', name: '#hashtagged' }].to_json, association.virtual_value.to_json
58
65
  end
59
66
  end
60
67
 
@@ -63,13 +70,19 @@ module ActiveModel
63
70
  .associations
64
71
  .detect { |assoc| assoc.key == :comments }
65
72
 
66
- assert association.serializer.first.custom_options[:custom_options]
73
+ comment_serializer = association.lazy_association.serializer.first
74
+ class << comment_serializer
75
+ def custom_options
76
+ instance_options
77
+ end
78
+ end
79
+ assert comment_serializer.custom_options.fetch(:custom_options)
67
80
  end
68
81
 
69
82
  def test_belongs_to
70
83
  @comment_serializer.associations.each do |association|
71
84
  key = association.key
72
- serializer = association.serializer
85
+ serializer = association.lazy_association.serializer
73
86
 
74
87
  case key
75
88
  when :post
@@ -80,7 +93,7 @@ module ActiveModel
80
93
  flunk "Unknown association: #{key}"
81
94
  end
82
95
 
83
- assert_equal({ include_data: true }, association.options)
96
+ assert_equal true, association.include_data?
84
97
  end
85
98
  end
86
99
 
@@ -104,13 +117,13 @@ module ActiveModel
104
117
  end
105
118
 
106
119
  assert(
107
- PostSerializer._reflections.all? do |reflection|
108
- inherited_klass._reflections.include?(reflection)
120
+ PostSerializer._reflections.values.all? do |reflection|
121
+ inherited_klass._reflections.values.include?(reflection)
109
122
  end
110
123
  )
111
124
 
112
125
  assert(
113
- inherited_klass._reflections.any? do |reflection|
126
+ inherited_klass._reflections.values.any? do |reflection|
114
127
  reflection.name == :top_comments
115
128
  end
116
129
  )
@@ -126,6 +139,78 @@ module ActiveModel
126
139
  assert expected_association_keys.include? :site
127
140
  end
128
141
 
142
+ class BelongsToBlogModel < ::Model
143
+ attributes :id, :title
144
+ associations :blog
145
+ end
146
+ class BelongsToBlogModelSerializer < ActiveModel::Serializer
147
+ type :posts
148
+ belongs_to :blog
149
+ end
150
+
151
+ def test_belongs_to_doesnt_load_record
152
+ attributes = { id: 1, title: 'Belongs to Blog', blog: Blog.new(id: 5) }
153
+ post = BelongsToBlogModel.new(attributes)
154
+ class << post
155
+ def blog
156
+ fail 'should use blog_id'
157
+ end
158
+
159
+ def blog_id
160
+ 5
161
+ end
162
+ end
163
+
164
+ actual =
165
+ begin
166
+ original_option = BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship
167
+ BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = true
168
+ serializable(post, adapter: :json_api, serializer: BelongsToBlogModelSerializer).as_json
169
+ ensure
170
+ BelongsToBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = original_option
171
+ end
172
+ expected = { data: { id: '1', type: 'posts', relationships: { blog: { data: { id: '5', type: 'blogs' } } } } }
173
+
174
+ assert_equal expected, actual
175
+ end
176
+
177
+ class ExternalBlog < Blog
178
+ attributes :external_id
179
+ end
180
+ class BelongsToExternalBlogModel < ::Model
181
+ attributes :id, :title, :external_blog_id
182
+ associations :external_blog
183
+ end
184
+ class BelongsToExternalBlogModelSerializer < ActiveModel::Serializer
185
+ type :posts
186
+ belongs_to :external_blog
187
+
188
+ def external_blog_id
189
+ object.external_blog.external_id
190
+ end
191
+ end
192
+
193
+ def test_belongs_to_allows_id_overwriting
194
+ attributes = {
195
+ id: 1,
196
+ title: 'Title',
197
+ external_blog: ExternalBlog.new(id: 5, external_id: 6)
198
+ }
199
+ post = BelongsToExternalBlogModel.new(attributes)
200
+
201
+ actual =
202
+ begin
203
+ original_option = BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship
204
+ BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = true
205
+ serializable(post, adapter: :json_api, serializer: BelongsToExternalBlogModelSerializer).as_json
206
+ ensure
207
+ BelongsToExternalBlogModelSerializer.config.jsonapi_use_foreign_key_on_belongs_to_relationship = original_option
208
+ end
209
+ expected = { data: { id: '1', type: 'posts', relationships: { :'external-blog' => { data: { id: '6', type: 'external-blogs' } } } } }
210
+
211
+ assert_equal expected, actual
212
+ end
213
+
129
214
  class InlineAssociationTestPostSerializer < ActiveModel::Serializer
130
215
  has_many :comments
131
216
  has_many :comments, key: :last_comments do
@@ -143,12 +228,12 @@ module ActiveModel
143
228
  )
144
229
  actual = serializable(post, adapter: :attributes, serializer: InlineAssociationTestPostSerializer).as_json
145
230
  expected = {
146
- :comments => [
147
- { :id => 1, :contents => 'first comment' },
148
- { :id => 2, :contents => 'last comment' }
231
+ comments: [
232
+ { id: 1, contents: 'first comment' },
233
+ { id: 2, contents: 'last comment' }
149
234
  ],
150
- :last_comments => [
151
- { :id => 2, :contents => 'last comment' }
235
+ last_comments: [
236
+ { id: 2, contents: 'last comment' }
152
237
  ]
153
238
  }
154
239
 
@@ -160,18 +245,20 @@ module ActiveModel
160
245
 
161
246
  class NamespacedResourcesTest < ActiveSupport::TestCase
162
247
  class ResourceNamespace
163
- Post = Class.new(::Model)
164
- Comment = Class.new(::Model)
165
- Author = Class.new(::Model)
166
- Description = Class.new(::Model)
248
+ class Post < ::Model
249
+ associations :comments, :author, :description
250
+ end
251
+ class Comment < ::Model; end
252
+ class Author < ::Model; end
253
+ class Description < ::Model; end
167
254
  class PostSerializer < ActiveModel::Serializer
168
255
  has_many :comments
169
256
  belongs_to :author
170
257
  has_one :description
171
258
  end
172
- CommentSerializer = Class.new(ActiveModel::Serializer)
173
- AuthorSerializer = Class.new(ActiveModel::Serializer)
174
- DescriptionSerializer = Class.new(ActiveModel::Serializer)
259
+ class CommentSerializer < ActiveModel::Serializer; end
260
+ class AuthorSerializer < ActiveModel::Serializer; end
261
+ class DescriptionSerializer < ActiveModel::Serializer; end
175
262
  end
176
263
 
177
264
  def setup
@@ -188,11 +275,61 @@ module ActiveModel
188
275
  @post_serializer.associations.each do |association|
189
276
  case association.key
190
277
  when :comments
191
- assert_instance_of(ResourceNamespace::CommentSerializer, association.serializer.first)
278
+ assert_instance_of(ResourceNamespace::CommentSerializer, association.lazy_association.serializer.first)
192
279
  when :author
193
- assert_instance_of(ResourceNamespace::AuthorSerializer, association.serializer)
280
+ assert_instance_of(ResourceNamespace::AuthorSerializer, association.lazy_association.serializer)
194
281
  when :description
195
- assert_instance_of(ResourceNamespace::DescriptionSerializer, association.serializer)
282
+ assert_instance_of(ResourceNamespace::DescriptionSerializer, association.lazy_association.serializer)
283
+ else
284
+ flunk "Unknown association: #{key}"
285
+ end
286
+ end
287
+ end
288
+ end
289
+
290
+ class AssociationsNamespacedSerializersTest < ActiveSupport::TestCase
291
+ class Post < ::Model
292
+ associations :comments, :author, :description
293
+
294
+ def latest_comments
295
+ comments[0..3]
296
+ end
297
+ end
298
+ class Comment < ::Model; end
299
+ class Author < ::Model; end
300
+ class Description < ::Model; end
301
+
302
+ class ResourceNamespace
303
+ class PostSerializer < ActiveModel::Serializer
304
+ has_many :comments, namespace: ResourceNamespace
305
+ has_many :latest_comments, namespace: ResourceNamespace
306
+ belongs_to :author, namespace: ResourceNamespace
307
+ has_one :description, namespace: ResourceNamespace
308
+ end
309
+ class CommentSerializer < ActiveModel::Serializer; end
310
+ class AuthorSerializer < ActiveModel::Serializer; end
311
+ class DescriptionSerializer < ActiveModel::Serializer; end
312
+ end
313
+
314
+ def setup
315
+ @comment = Comment.new
316
+ @author = Author.new
317
+ @description = Description.new
318
+ @post = Post.new(comments: [@comment],
319
+ author: @author,
320
+ description: @description)
321
+ @post_serializer = ResourceNamespace::PostSerializer.new(@post)
322
+ end
323
+
324
+ def test_associations_namespaced_serializers
325
+ @post_serializer.associations.each do |association|
326
+ case association.key
327
+ when :comments, :latest_comments
328
+ assert_instance_of(ResourceNamespace::CommentSerializer, association.lazy_association.serializer.first)
329
+ when :author
330
+ assert_instance_of(ResourceNamespace::AuthorSerializer, association.lazy_association.serializer)
331
+ when :description
332
+ assert_instance_of(ResourceNamespace::DescriptionSerializer, association.lazy_association.serializer)
196
333
  else
197
334
  flunk "Unknown association: #{key}"
198
335
  end
@@ -201,17 +338,19 @@ module ActiveModel
201
338
  end
202
339
 
203
340
  class NestedSerializersTest < ActiveSupport::TestCase
204
- Post = Class.new(::Model)
205
- Comment = Class.new(::Model)
206
- Author = Class.new(::Model)
207
- Description = Class.new(::Model)
341
+ class Post < ::Model
342
+ associations :comments, :author, :description
343
+ end
344
+ class Comment < ::Model; end
345
+ class Author < ::Model; end
346
+ class Description < ::Model; end
208
347
  class PostSerializer < ActiveModel::Serializer
209
348
  has_many :comments
210
- CommentSerializer = Class.new(ActiveModel::Serializer)
349
+ class CommentSerializer < ActiveModel::Serializer; end
211
350
  belongs_to :author
212
- AuthorSerializer = Class.new(ActiveModel::Serializer)
351
+ class AuthorSerializer < ActiveModel::Serializer; end
213
352
  has_one :description
214
- DescriptionSerializer = Class.new(ActiveModel::Serializer)
353
+ class DescriptionSerializer < ActiveModel::Serializer; end
215
354
  end
216
355
 
217
356
  def setup
@@ -228,11 +367,11 @@ module ActiveModel
228
367
  @post_serializer.associations.each do |association|
229
368
  case association.key
230
369
  when :comments
231
- assert_instance_of(PostSerializer::CommentSerializer, association.serializer.first)
370
+ assert_instance_of(PostSerializer::CommentSerializer, association.lazy_association.serializer.first)
232
371
  when :author
233
- assert_instance_of(PostSerializer::AuthorSerializer, association.serializer)
372
+ assert_instance_of(PostSerializer::AuthorSerializer, association.lazy_association.serializer)
234
373
  when :description
235
- assert_instance_of(PostSerializer::DescriptionSerializer, association.serializer)
374
+ assert_instance_of(PostSerializer::DescriptionSerializer, association.lazy_association.serializer)
236
375
  else
237
376
  flunk "Unknown association: #{key}"
238
377
  end
@@ -241,7 +380,10 @@ module ActiveModel
241
380
 
242
381
  # rubocop:disable Metrics/AbcSize
243
382
  def test_conditional_associations
244
- model = ::Model.new(true: true, false: false)
383
+ model = Class.new(::Model) do
384
+ attributes :true, :false
385
+ associations :something
386
+ end.new(true: true, false: false)
245
387
 
246
388
  scenarios = [
247
389
  { options: { if: :true }, included: true },
@@ -264,7 +406,7 @@ module ActiveModel
264
406
 
265
407
  scenarios.each do |s|
266
408
  serializer = Class.new(ActiveModel::Serializer) do
267
- belongs_to :association, s[:options]
409
+ belongs_to :something, s[:options]
268
410
 
269
411
  def true
270
412
  true
@@ -276,7 +418,7 @@ module ActiveModel
276
418
  end
277
419
 
278
420
  hash = serializable(model, serializer: serializer).serializable_hash
279
- assert_equal(s[:included], hash.key?(:association), "Error with #{s[:options]}")
421
+ assert_equal(s[:included], hash.key?(:something), "Error with #{s[:options]}")
280
422
  end
281
423
  end
282
424
 
@@ -290,6 +432,89 @@ module ActiveModel
290
432
  assert_match(/:if should be a Symbol, String or Proc/, exception.message)
291
433
  end
292
434
  end
435
+
436
+ class InheritedSerializerTest < ActiveSupport::TestCase
437
+ class PostSerializer < ActiveModel::Serializer
438
+ belongs_to :author
439
+ has_many :comments
440
+ belongs_to :blog
441
+ end
442
+
443
+ class InheritedPostSerializer < PostSerializer
444
+ belongs_to :author, polymorphic: true
445
+ has_many :comments, key: :reviews
446
+ end
447
+
448
+ class AuthorSerializer < ActiveModel::Serializer
449
+ has_many :posts
450
+ has_many :roles
451
+ has_one :bio
452
+ end
453
+
454
+ class InheritedAuthorSerializer < AuthorSerializer
455
+ has_many :roles, polymorphic: true
456
+ has_one :bio, polymorphic: true
457
+ end
458
+
459
+ def setup
460
+ @author = Author.new(name: 'Steve K.')
461
+ @post = Post.new(title: 'New Post', body: 'Body')
462
+ @post_serializer = PostSerializer.new(@post)
463
+ @author_serializer = AuthorSerializer.new(@author)
464
+ @inherited_post_serializer = InheritedPostSerializer.new(@post)
465
+ @inherited_author_serializer = InheritedAuthorSerializer.new(@author)
466
+ @author_associations = @author_serializer.associations.to_a.sort_by(&:name)
467
+ @inherited_author_associations = @inherited_author_serializer.associations.to_a.sort_by(&:name)
468
+ @post_associations = @post_serializer.associations.to_a
469
+ @inherited_post_associations = @inherited_post_serializer.associations.to_a
470
+ end
471
+
472
+ test 'an author serializer must have [posts,roles,bio] associations' do
473
+ expected = [:posts, :roles, :bio].sort
474
+ result = @author_serializer.associations.map(&:name).sort
475
+ assert_equal(result, expected)
476
+ end
477
+
478
+ test 'a post serializer must have [author,comments,blog] associations' do
479
+ expected = [:author, :comments, :blog].sort
480
+ result = @post_serializer.associations.map(&:name).sort
481
+ assert_equal(result, expected)
482
+ end
483
+
484
+ test 'a serializer inheriting from another serializer can redefine has_many and has_one associations' do
485
+ expected = [:roles, :bio].sort
486
+ result = (@inherited_author_associations.map(&:reflection) - @author_associations.map(&:reflection)).map(&:name)
487
+ assert_equal(result, expected)
488
+ assert_equal [true, false, true], @inherited_author_associations.map(&:polymorphic?)
489
+ assert_equal [false, false, false], @author_associations.map(&:polymorphic?)
490
+ end
491
+
492
+ test 'a serializer inheriting from another serializer can redefine belongs_to associations' do
493
+ assert_equal [:author, :comments, :blog], @post_associations.map(&:name)
494
+ assert_equal [:author, :comments, :blog, :comments], @inherited_post_associations.map(&:name)
495
+
496
+ refute @post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
497
+ assert @inherited_post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
498
+
499
+ refute @post_associations.detect { |assoc| assoc.name == :comments }.key?
500
+ original_comment_assoc, new_comments_assoc = @inherited_post_associations.select { |assoc| assoc.name == :comments }
501
+ refute original_comment_assoc.key?
502
+ assert_equal :reviews, new_comments_assoc.key
503
+
504
+ original_blog = @post_associations.detect { |assoc| assoc.name == :blog }
505
+ inherited_blog = @inherited_post_associations.detect { |assoc| assoc.name == :blog }
506
+ original_parent_serializer = original_blog.lazy_association.association_options.delete(:parent_serializer)
507
+ inherited_parent_serializer = inherited_blog.lazy_association.association_options.delete(:parent_serializer)
508
+ assert_equal PostSerializer, original_parent_serializer.class
509
+ assert_equal InheritedPostSerializer, inherited_parent_serializer.class
510
+ end
511
+
512
+ test 'a serializer inheriting from another serializer can have an additional association with the same name but with different key' do
513
+ expected = [:author, :comments, :blog, :reviews].sort
514
+ result = @inherited_post_serializer.associations.map(&:key).sort
515
+ assert_equal(result, expected)
516
+ end
517
+ end
293
518
  end
294
519
  end
295
520
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
@@ -22,7 +24,7 @@ module ActiveModel
22
24
  inherited_klass = Class.new(AlternateBlogSerializer)
23
25
  blog_serializer = inherited_klass.new(@blog)
24
26
  adapter = ActiveModelSerializers::Adapter::Attributes.new(blog_serializer)
25
- assert_equal({ :id => 1, :title => 'AMS Hints' }, adapter.serializable_hash)
27
+ assert_equal({ id: 1, title: 'AMS Hints' }, adapter.serializable_hash)
26
28
  end
27
29
 
28
30
  def test_multiple_calls_with_the_same_attribute
@@ -81,7 +83,7 @@ module ActiveModel
81
83
  assert_equal('custom', hash[:blog][:id])
82
84
  end
83
85
 
84
- PostWithVirtualAttribute = Class.new(::Model)
86
+ class PostWithVirtualAttribute < ::Model; attributes :first_name, :last_name end
85
87
  class PostWithVirtualAttributeSerializer < ActiveModel::Serializer
86
88
  attribute :name do
87
89
  "#{object.first_name} #{object.last_name}"
@@ -98,7 +100,9 @@ module ActiveModel
98
100
 
99
101
  # rubocop:disable Metrics/AbcSize
100
102
  def test_conditional_associations
101
- model = ::Model.new(true: true, false: false)
103
+ model = Class.new(::Model) do
104
+ attributes :true, :false, :attribute
105
+ end.new(true: true, false: false)
102
106
 
103
107
  scenarios = [
104
108
  { options: { if: :true }, included: true },
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
4
6
  class Serializer
5
7
  class AttributesTest < ActiveSupport::TestCase
6
8
  def setup
7
- @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
9
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
8
10
  @profile_serializer = ProfileSerializer.new(@profile)
9
11
  @comment = Comment.new(id: 1, body: 'ZOMG!!', date: '2015')
10
12
  @serializer_klass = Class.new(CommentSerializer)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Execute this test in isolation
2
4
  require 'support/isolated_unit'
3
5
 
@@ -69,9 +71,9 @@ class CachingConfigurationTest < ActiveSupport::TestCase
69
71
  end
70
72
 
71
73
  test 'the non-cached serializer cache_store is nil' do
72
- assert_equal nil, @non_cached_serializer._cache
73
- assert_equal nil, @non_cached_serializer.cache_store
74
- assert_equal nil, @non_cached_serializer._cache
74
+ assert_nil @non_cached_serializer._cache
75
+ assert_nil @non_cached_serializer.cache_store
76
+ assert_nil @non_cached_serializer._cache
75
77
  end
76
78
 
77
79
  test 'the non-cached serializer does not have cache_enabled?' do
@@ -136,9 +138,9 @@ class CachingConfigurationTest < ActiveSupport::TestCase
136
138
  end
137
139
 
138
140
  test 'the non-cached serializer cache_store is nil' do
139
- assert_equal nil, @non_cached_serializer._cache
140
- assert_equal nil, @non_cached_serializer.cache_store
141
- assert_equal nil, @non_cached_serializer._cache
141
+ assert_nil @non_cached_serializer._cache
142
+ assert_nil @non_cached_serializer.cache_store
143
+ assert_nil @non_cached_serializer._cache
142
144
  end
143
145
 
144
146
  test 'the non-cached serializer does not have cache_enabled?' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
@@ -5,7 +7,7 @@ module ActiveModel
5
7
  class FieldsetTest < ActiveSupport::TestCase
6
8
  def test_fieldset_with_hash
7
9
  fieldset = ActiveModel::Serializer::Fieldset.new('post' => %w(id title), 'comment' => ['body'])
8
- expected = { :post => [:id, :title], :comment => [:body] }
10
+ expected = { post: [:id, :title], comment: [:body] }
9
11
 
10
12
  assert_equal(expected, fieldset.fields)
11
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'test_helper'
2
4
 
3
5
  module ActiveModel
@@ -15,7 +17,8 @@ module ActiveModel
15
17
  @blog,
16
18
  adapter: :json,
17
19
  serializer: AlternateBlogSerializer,
18
- meta: { total: 10 }).as_json
20
+ meta: { total: 10 }
21
+ ).as_json
19
22
  expected = {
20
23
  blog: {
21
24
  id: 1,
@@ -65,7 +68,8 @@ module ActiveModel
65
68
  @blog,
66
69
  adapter: :attributes,
67
70
  serializer: AlternateBlogSerializer,
68
- meta: { total: 10 }).as_json
71
+ meta: { total: 10 }
72
+ ).as_json
69
73
  expected = {
70
74
  id: 1,
71
75
  title: 'AMS Hints'
@@ -79,7 +83,8 @@ module ActiveModel
79
83
  adapter: :json,
80
84
  serializer: AlternateBlogSerializer,
81
85
  meta: { total: 10 },
82
- meta_key: 'haha_meta').as_json
86
+ meta_key: 'haha_meta'
87
+ ).as_json
83
88
  expected = {
84
89
  blog: {
85
90
  id: 1,
@@ -98,7 +103,8 @@ module ActiveModel
98
103
  adapter: :json_api,
99
104
  serializer: AlternateBlogSerializer,
100
105
  meta: { total: 10 },
101
- meta_key: 'haha_meta').as_json
106
+ meta_key: 'haha_meta'
107
+ ).as_json
102
108
  expected = {
103
109
  data: {
104
110
  id: '1',
@@ -148,7 +154,8 @@ module ActiveModel
148
154
  actual = ActiveModelSerializers::SerializableResource.new(
149
155
  [@blog],
150
156
  adapter: :attributes,
151
- meta: { total: 10 }).as_json
157
+ meta: { total: 10 }
158
+ ).as_json
152
159
  expected = [{
153
160
  id: 1,
154
161
  name: 'AMS Hints',
@@ -170,7 +177,8 @@ module ActiveModel
170
177
  [@blog],
171
178
  adapter: :json,
172
179
  meta: { total: 10 },
173
- meta_key: 'haha_meta').as_json
180
+ meta_key: 'haha_meta'
181
+ ).as_json
174
182
  expected = {
175
183
  blogs: [{
176
184
  id: 1,