active_model_serializers 0.10.0 → 0.10.6

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 (168) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -5
  3. data/.travis.yml +17 -5
  4. data/CHANGELOG.md +126 -2
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +5 -2
  7. data/README.md +166 -26
  8. data/Rakefile +3 -32
  9. data/active_model_serializers.gemspec +22 -25
  10. data/appveyor.yml +9 -3
  11. data/bin/rubocop +38 -0
  12. data/docs/README.md +2 -1
  13. data/docs/general/adapters.md +29 -11
  14. data/docs/general/caching.md +7 -1
  15. data/docs/general/configuration_options.md +70 -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 +62 -24
  21. data/docs/general/serializers.md +121 -13
  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 +4 -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 +35 -12
  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 +296 -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 +1 -1
  52. data/lib/active_model_serializers/adapter/json_api/link.rb +1 -1
  53. data/lib/active_model_serializers/adapter/json_api/pagination_links.rb +8 -1
  54. data/lib/active_model_serializers/adapter/json_api/relationship.rb +63 -23
  55. data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +32 -9
  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 +15 -0
  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/errors_test.rb +8 -9
  78. data/test/action_controller/json_api/fields_test.rb +66 -0
  79. data/test/action_controller/json_api/linked_test.rb +29 -24
  80. data/test/action_controller/json_api/pagination_test.rb +19 -19
  81. data/test/action_controller/json_api/transform_test.rb +11 -3
  82. data/test/action_controller/lookup_proc_test.rb +49 -0
  83. data/test/action_controller/namespace_lookup_test.rb +232 -0
  84. data/test/action_controller/serialization_scope_name_test.rb +12 -6
  85. data/test/action_controller/serialization_test.rb +12 -9
  86. data/test/active_model_serializers/json_pointer_test.rb +15 -13
  87. data/test/active_model_serializers/model_test.rb +137 -4
  88. data/test/active_model_serializers/railtie_test_isolated.rb +12 -7
  89. data/test/active_model_serializers/register_jsonapi_renderer_test_isolated.rb +161 -0
  90. data/test/active_model_serializers/serialization_context_test_isolated.rb +23 -10
  91. data/test/active_model_serializers/test/schema_test.rb +3 -2
  92. data/test/adapter/attributes_test.rb +40 -0
  93. data/test/adapter/json/collection_test.rb +14 -0
  94. data/test/adapter/json/has_many_test.rb +10 -2
  95. data/test/adapter/json/transform_test.rb +15 -15
  96. data/test/adapter/json_api/collection_test.rb +4 -3
  97. data/test/adapter/json_api/errors_test.rb +17 -19
  98. data/test/adapter/json_api/fields_test.rb +12 -3
  99. data/test/adapter/json_api/has_many_test.rb +49 -20
  100. data/test/adapter/json_api/include_data_if_sideloaded_test.rb +183 -0
  101. data/test/adapter/json_api/json_api_test.rb +5 -7
  102. data/test/adapter/json_api/linked_test.rb +33 -12
  103. data/test/adapter/json_api/links_test.rb +4 -2
  104. data/test/adapter/json_api/pagination_links_test.rb +35 -8
  105. data/test/adapter/json_api/relationship_test.rb +309 -73
  106. data/test/adapter/json_api/resource_identifier_test.rb +27 -2
  107. data/test/adapter/json_api/resource_meta_test.rb +3 -3
  108. data/test/adapter/json_api/transform_test.rb +263 -253
  109. data/test/adapter/json_api/type_test.rb +1 -1
  110. data/test/adapter/json_test.rb +8 -7
  111. data/test/adapter/null_test.rb +1 -2
  112. data/test/adapter/polymorphic_test.rb +5 -5
  113. data/test/adapter_test.rb +1 -1
  114. data/test/benchmark/app.rb +1 -1
  115. data/test/benchmark/benchmarking_support.rb +1 -1
  116. data/test/benchmark/bm_active_record.rb +81 -0
  117. data/test/benchmark/bm_adapter.rb +38 -0
  118. data/test/benchmark/bm_caching.rb +16 -16
  119. data/test/benchmark/bm_lookup_chain.rb +83 -0
  120. data/test/benchmark/bm_transform.rb +21 -10
  121. data/test/benchmark/controllers.rb +16 -17
  122. data/test/benchmark/fixtures.rb +72 -72
  123. data/test/cache_test.rb +235 -69
  124. data/test/collection_serializer_test.rb +25 -12
  125. data/test/fixtures/active_record.rb +45 -10
  126. data/test/fixtures/poro.rb +124 -181
  127. data/test/generators/serializer_generator_test.rb +23 -5
  128. data/test/grape_test.rb +170 -56
  129. data/test/lint_test.rb +1 -1
  130. data/test/logger_test.rb +13 -11
  131. data/test/serializable_resource_test.rb +18 -22
  132. data/test/serializers/association_macros_test.rb +3 -2
  133. data/test/serializers/associations_test.rb +178 -49
  134. data/test/serializers/attribute_test.rb +5 -3
  135. data/test/serializers/attributes_test.rb +1 -1
  136. data/test/serializers/caching_configuration_test_isolated.rb +6 -6
  137. data/test/serializers/fieldset_test.rb +1 -1
  138. data/test/serializers/meta_test.rb +12 -6
  139. data/test/serializers/options_test.rb +17 -6
  140. data/test/serializers/read_attribute_for_serialization_test.rb +3 -3
  141. data/test/serializers/reflection_test.rb +427 -0
  142. data/test/serializers/root_test.rb +1 -1
  143. data/test/serializers/serialization_test.rb +2 -2
  144. data/test/serializers/serializer_for_test.rb +12 -10
  145. data/test/serializers/serializer_for_with_namespace_test.rb +88 -0
  146. data/test/support/isolated_unit.rb +5 -2
  147. data/test/support/rails5_shims.rb +8 -2
  148. data/test/support/rails_app.rb +2 -9
  149. data/test/support/serialization_testing.rb +23 -5
  150. data/test/test_helper.rb +13 -0
  151. metadata +105 -42
  152. data/.rubocop_todo.yml +0 -167
  153. data/docs/ARCHITECTURE.md +0 -126
  154. data/lib/active_model/serializer/associations.rb +0 -100
  155. data/lib/active_model/serializer/attributes.rb +0 -82
  156. data/lib/active_model/serializer/collection_reflection.rb +0 -7
  157. data/lib/active_model/serializer/configuration.rb +0 -35
  158. data/lib/active_model/serializer/include_tree.rb +0 -111
  159. data/lib/active_model/serializer/links.rb +0 -35
  160. data/lib/active_model/serializer/meta.rb +0 -29
  161. data/lib/active_model/serializer/singular_reflection.rb +0 -7
  162. data/lib/active_model/serializer/type.rb +0 -25
  163. data/lib/active_model_serializers/key_transform.rb +0 -70
  164. data/test/active_model_serializers/key_transform_test.rb +0 -263
  165. data/test/adapter/json_api/relationships_test.rb +0 -199
  166. data/test/include_tree/from_include_args_test.rb +0 -26
  167. data/test/include_tree/from_string_test.rb +0 -94
  168. data/test/include_tree/include_args_to_hash_test.rb +0 -64
data/test/lint_test.rb CHANGED
@@ -30,7 +30,7 @@ module ActiveModel
30
30
  def errors
31
31
  end
32
32
 
33
- def self.human_attribute_name(attr, options = {})
33
+ def self.human_attribute_name(_, _ = {})
34
34
  end
35
35
 
36
36
  def self.lookup_ancestors
data/test/logger_test.rb CHANGED
@@ -1,18 +1,20 @@
1
1
  require 'test_helper'
2
2
 
3
- class ActiveModelSerializers::LoggerTest < ActiveSupport::TestCase
4
- def test_logger_is_set_to_action_controller_logger_when_initializer_runs
5
- assert_equal $action_controller_logger, ActionController::Base.logger # rubocop:disable Style/GlobalVars
6
- end
3
+ module ActiveModelSerializers
4
+ class LoggerTest < ActiveSupport::TestCase
5
+ def test_logger_is_set_to_action_controller_logger_when_initializer_runs
6
+ assert_equal $action_controller_logger, ActionController::Base.logger # rubocop:disable Style/GlobalVars
7
+ end
7
8
 
8
- def test_logger_can_be_set
9
- original_logger = ActiveModelSerializers.logger
10
- logger = Logger.new(STDOUT)
9
+ def test_logger_can_be_set
10
+ original_logger = ActiveModelSerializers.logger
11
+ logger = Logger.new(STDOUT)
11
12
 
12
- ActiveModelSerializers.logger = logger
13
+ ActiveModelSerializers.logger = logger
13
14
 
14
- assert_equal ActiveModelSerializers.logger, logger
15
- ensure
16
- ActiveModelSerializers.logger = original_logger
15
+ assert_equal ActiveModelSerializers.logger, logger
16
+ ensure
17
+ ActiveModelSerializers.logger = original_logger
18
+ end
17
19
  end
18
20
  end
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  module ActiveModelSerializers
4
4
  class SerializableResourceTest < ActiveSupport::TestCase
5
5
  def setup
6
- @resource = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
6
+ @resource = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
7
7
  @serializer = ProfileSerializer.new(@resource)
8
8
  @adapter = ActiveModelSerializers::Adapter.create(@serializer)
9
9
  @serializable_resource = SerializableResource.new(@resource)
@@ -32,11 +32,11 @@ module ActiveModelSerializers
32
32
  end
33
33
 
34
34
  def test_use_adapter_with_adapter_option
35
- assert SerializableResource.new(@resource, { adapter: 'json' }).use_adapter?
35
+ assert SerializableResource.new(@resource, adapter: 'json').use_adapter?
36
36
  end
37
37
 
38
38
  def test_use_adapter_with_adapter_option_as_false
39
- refute SerializableResource.new(@resource, { adapter: false }).use_adapter?
39
+ refute SerializableResource.new(@resource, adapter: false).use_adapter?
40
40
  end
41
41
 
42
42
  class SerializableResourceErrorsTest < Minitest::Test
@@ -45,15 +45,13 @@ module ActiveModelSerializers
45
45
  resource = ModelWithErrors.new
46
46
  resource.errors.add(:name, 'must be awesome')
47
47
  serializable_resource = ActiveModelSerializers::SerializableResource.new(
48
- resource, {
49
- serializer: ActiveModel::Serializer::ErrorSerializer,
50
- adapter: :json_api
51
- })
52
- expected_response_document =
53
- { :errors =>
54
- [
55
- { :source => { :pointer => '/data/attributes/name' }, :detail => 'must be awesome' }
56
- ]
48
+ resource, serializer: ActiveModel::Serializer::ErrorSerializer,
49
+ adapter: :json_api
50
+ )
51
+ expected_response_document = {
52
+ errors: [
53
+ { source: { pointer: '/data/attributes/name' }, detail: 'must be awesome' }
54
+ ]
57
55
  }
58
56
  assert_equal serializable_resource.as_json(options), expected_response_document
59
57
  end
@@ -65,16 +63,14 @@ module ActiveModelSerializers
65
63
  resource.errors.add(:title, 'must be amazing')
66
64
  resources << ModelWithErrors.new
67
65
  serializable_resource = SerializableResource.new(
68
- resources, {
69
- serializer: ActiveModel::Serializer::ErrorsSerializer,
70
- each_serializer: ActiveModel::Serializer::ErrorSerializer,
71
- adapter: :json_api
72
- })
73
- expected_response_document =
74
- { :errors =>
75
- [
76
- { :source => { :pointer => '/data/attributes/title' }, :detail => 'must be amazing' }
77
- ]
66
+ resources, serializer: ActiveModel::Serializer::ErrorsSerializer,
67
+ each_serializer: ActiveModel::Serializer::ErrorSerializer,
68
+ adapter: :json_api
69
+ )
70
+ expected_response_document = {
71
+ errors: [
72
+ { source: { pointer: '/data/attributes/title' }, detail: 'must be amazing' }
73
+ ]
78
74
  }
79
75
  assert_equal serializable_resource.as_json(options), expected_response_document
80
76
  end
@@ -3,7 +3,8 @@ require 'test_helper'
3
3
  module ActiveModel
4
4
  class Serializer
5
5
  class AssociationMacrosTest < ActiveSupport::TestCase
6
- AuthorSummarySerializer = Class.new
6
+ class AuthorSummarySerializer < ActiveModel::Serializer; end
7
+
7
8
  class AssociationsTestSerializer < Serializer
8
9
  belongs_to :author, serializer: AuthorSummarySerializer
9
10
  has_many :comments
@@ -11,7 +12,7 @@ module ActiveModel
11
12
  end
12
13
 
13
14
  def before_setup
14
- @reflections = AssociationsTestSerializer._reflections
15
+ @reflections = AssociationsTestSerializer._reflections.values
15
16
  end
16
17
 
17
18
  def test_has_one_defines_reflection
@@ -1,16 +1,19 @@
1
1
  require 'test_helper'
2
-
3
2
  module ActiveModel
4
3
  class Serializer
5
4
  class AssociationsTest < ActiveSupport::TestCase
5
+ class ModelWithoutSerializer < ::Model
6
+ attributes :id, :name
7
+ end
8
+
6
9
  def setup
7
10
  @author = Author.new(name: 'Steve K.')
8
11
  @author.bio = nil
9
12
  @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' })
13
+ @blog = Blog.new(name: 'AMS Blog')
14
+ @post = Post.new(title: 'New Post', body: 'Body')
15
+ @tag = ModelWithoutSerializer.new(id: 'tagid', name: '#hashtagged')
16
+ @comment = Comment.new(id: 1, body: 'ZOMG A COMMENT')
14
17
  @post.comments = [@comment]
15
18
  @post.tags = [@tag]
16
19
  @post.blog = @blog
@@ -19,7 +22,7 @@ module ActiveModel
19
22
  @post.author = @author
20
23
  @author.posts = [@post]
21
24
 
22
- @post_serializer = PostSerializer.new(@post, { custom_options: true })
25
+ @post_serializer = PostSerializer.new(@post, custom_options: true)
23
26
  @author_serializer = AuthorSerializer.new(@author)
24
27
  @comment_serializer = CommentSerializer.new(@comment)
25
28
  end
@@ -27,18 +30,17 @@ module ActiveModel
27
30
  def test_has_many_and_has_one
28
31
  @author_serializer.associations.each do |association|
29
32
  key = association.key
30
- serializer = association.serializer
31
- options = association.options
33
+ serializer = association.lazy_association.serializer
32
34
 
33
35
  case key
34
36
  when :posts
35
- assert_equal({ include_data: true }, options)
37
+ assert_equal true, association.include_data?
36
38
  assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
37
39
  when :bio
38
- assert_equal({ include_data: true }, options)
40
+ assert_equal true, association.include_data?
39
41
  assert_nil serializer
40
42
  when :roles
41
- assert_equal({ include_data: true }, options)
43
+ assert_equal true, association.include_data?
42
44
  assert_kind_of(ActiveModelSerializers.config.collection_serializer, serializer)
43
45
  else
44
46
  flunk "Unknown association: #{key}"
@@ -47,14 +49,17 @@ module ActiveModel
47
49
  end
48
50
 
49
51
  def test_has_many_with_no_serializer
50
- PostWithTagsSerializer.new(@post).associations.each do |association|
52
+ post_serializer_class = Class.new(ActiveModel::Serializer) do
53
+ attributes :id
54
+ has_many :tags
55
+ end
56
+ post_serializer_class.new(@post).associations.each do |association|
51
57
  key = association.key
52
- serializer = association.serializer
53
- options = association.options
58
+ serializer = association.lazy_association.serializer
54
59
 
55
60
  assert_equal :tags, key
56
61
  assert_nil serializer
57
- assert_equal [{ name: '#hashtagged' }].to_json, options[:virtual_value].to_json
62
+ assert_equal [{ id: 'tagid', name: '#hashtagged' }].to_json, association.virtual_value.to_json
58
63
  end
59
64
  end
60
65
 
@@ -63,13 +68,19 @@ module ActiveModel
63
68
  .associations
64
69
  .detect { |assoc| assoc.key == :comments }
65
70
 
66
- assert association.serializer.first.custom_options[:custom_options]
71
+ comment_serializer = association.lazy_association.serializer.first
72
+ class << comment_serializer
73
+ def custom_options
74
+ instance_options
75
+ end
76
+ end
77
+ assert comment_serializer.custom_options.fetch(:custom_options)
67
78
  end
68
79
 
69
80
  def test_belongs_to
70
81
  @comment_serializer.associations.each do |association|
71
82
  key = association.key
72
- serializer = association.serializer
83
+ serializer = association.lazy_association.serializer
73
84
 
74
85
  case key
75
86
  when :post
@@ -80,7 +91,7 @@ module ActiveModel
80
91
  flunk "Unknown association: #{key}"
81
92
  end
82
93
 
83
- assert_equal({ include_data: true }, association.options)
94
+ assert_equal true, association.include_data?
84
95
  end
85
96
  end
86
97
 
@@ -104,13 +115,13 @@ module ActiveModel
104
115
  end
105
116
 
106
117
  assert(
107
- PostSerializer._reflections.all? do |reflection|
108
- inherited_klass._reflections.include?(reflection)
118
+ PostSerializer._reflections.values.all? do |reflection|
119
+ inherited_klass._reflections.values.include?(reflection)
109
120
  end
110
121
  )
111
122
 
112
123
  assert(
113
- inherited_klass._reflections.any? do |reflection|
124
+ inherited_klass._reflections.values.any? do |reflection|
114
125
  reflection.name == :top_comments
115
126
  end
116
127
  )
@@ -126,6 +137,34 @@ module ActiveModel
126
137
  assert expected_association_keys.include? :site
127
138
  end
128
139
 
140
+ class BelongsToBlogModel < ::Model
141
+ attributes :id, :title
142
+ associations :blog
143
+ end
144
+ class BelongsToBlogModelSerializer < ActiveModel::Serializer
145
+ type :posts
146
+ belongs_to :blog
147
+ end
148
+
149
+ def test_belongs_to_doesnt_load_record
150
+ attributes = { id: 1, title: 'Belongs to Blog', blog: Blog.new(id: 5) }
151
+ post = BelongsToBlogModel.new(attributes)
152
+ class << post
153
+ def blog
154
+ fail 'should use blog_id'
155
+ end
156
+
157
+ def blog_id
158
+ 5
159
+ end
160
+ end
161
+
162
+ actual = serializable(post, adapter: :json_api, serializer: BelongsToBlogModelSerializer).as_json
163
+ expected = { data: { id: '1', type: 'posts', relationships: { blog: { data: { id: '5', type: 'blogs' } } } } }
164
+
165
+ assert_equal expected, actual
166
+ end
167
+
129
168
  class InlineAssociationTestPostSerializer < ActiveModel::Serializer
130
169
  has_many :comments
131
170
  has_many :comments, key: :last_comments do
@@ -143,12 +182,12 @@ module ActiveModel
143
182
  )
144
183
  actual = serializable(post, adapter: :attributes, serializer: InlineAssociationTestPostSerializer).as_json
145
184
  expected = {
146
- :comments => [
147
- { :id => 1, :contents => 'first comment' },
148
- { :id => 2, :contents => 'last comment' }
185
+ comments: [
186
+ { id: 1, contents: 'first comment' },
187
+ { id: 2, contents: 'last comment' }
149
188
  ],
150
- :last_comments => [
151
- { :id => 2, :contents => 'last comment' }
189
+ last_comments: [
190
+ { id: 2, contents: 'last comment' }
152
191
  ]
153
192
  }
154
193
 
@@ -160,18 +199,20 @@ module ActiveModel
160
199
 
161
200
  class NamespacedResourcesTest < ActiveSupport::TestCase
162
201
  class ResourceNamespace
163
- Post = Class.new(::Model)
164
- Comment = Class.new(::Model)
165
- Author = Class.new(::Model)
166
- Description = Class.new(::Model)
202
+ class Post < ::Model
203
+ associations :comments, :author, :description
204
+ end
205
+ class Comment < ::Model; end
206
+ class Author < ::Model; end
207
+ class Description < ::Model; end
167
208
  class PostSerializer < ActiveModel::Serializer
168
209
  has_many :comments
169
210
  belongs_to :author
170
211
  has_one :description
171
212
  end
172
- CommentSerializer = Class.new(ActiveModel::Serializer)
173
- AuthorSerializer = Class.new(ActiveModel::Serializer)
174
- DescriptionSerializer = Class.new(ActiveModel::Serializer)
213
+ class CommentSerializer < ActiveModel::Serializer; end
214
+ class AuthorSerializer < ActiveModel::Serializer; end
215
+ class DescriptionSerializer < ActiveModel::Serializer; end
175
216
  end
176
217
 
177
218
  def setup
@@ -188,11 +229,11 @@ module ActiveModel
188
229
  @post_serializer.associations.each do |association|
189
230
  case association.key
190
231
  when :comments
191
- assert_instance_of(ResourceNamespace::CommentSerializer, association.serializer.first)
232
+ assert_instance_of(ResourceNamespace::CommentSerializer, association.lazy_association.serializer.first)
192
233
  when :author
193
- assert_instance_of(ResourceNamespace::AuthorSerializer, association.serializer)
234
+ assert_instance_of(ResourceNamespace::AuthorSerializer, association.lazy_association.serializer)
194
235
  when :description
195
- assert_instance_of(ResourceNamespace::DescriptionSerializer, association.serializer)
236
+ assert_instance_of(ResourceNamespace::DescriptionSerializer, association.lazy_association.serializer)
196
237
  else
197
238
  flunk "Unknown association: #{key}"
198
239
  end
@@ -201,17 +242,19 @@ module ActiveModel
201
242
  end
202
243
 
203
244
  class NestedSerializersTest < ActiveSupport::TestCase
204
- Post = Class.new(::Model)
205
- Comment = Class.new(::Model)
206
- Author = Class.new(::Model)
207
- Description = Class.new(::Model)
245
+ class Post < ::Model
246
+ associations :comments, :author, :description
247
+ end
248
+ class Comment < ::Model; end
249
+ class Author < ::Model; end
250
+ class Description < ::Model; end
208
251
  class PostSerializer < ActiveModel::Serializer
209
252
  has_many :comments
210
- CommentSerializer = Class.new(ActiveModel::Serializer)
253
+ class CommentSerializer < ActiveModel::Serializer; end
211
254
  belongs_to :author
212
- AuthorSerializer = Class.new(ActiveModel::Serializer)
255
+ class AuthorSerializer < ActiveModel::Serializer; end
213
256
  has_one :description
214
- DescriptionSerializer = Class.new(ActiveModel::Serializer)
257
+ class DescriptionSerializer < ActiveModel::Serializer; end
215
258
  end
216
259
 
217
260
  def setup
@@ -228,11 +271,11 @@ module ActiveModel
228
271
  @post_serializer.associations.each do |association|
229
272
  case association.key
230
273
  when :comments
231
- assert_instance_of(PostSerializer::CommentSerializer, association.serializer.first)
274
+ assert_instance_of(PostSerializer::CommentSerializer, association.lazy_association.serializer.first)
232
275
  when :author
233
- assert_instance_of(PostSerializer::AuthorSerializer, association.serializer)
276
+ assert_instance_of(PostSerializer::AuthorSerializer, association.lazy_association.serializer)
234
277
  when :description
235
- assert_instance_of(PostSerializer::DescriptionSerializer, association.serializer)
278
+ assert_instance_of(PostSerializer::DescriptionSerializer, association.lazy_association.serializer)
236
279
  else
237
280
  flunk "Unknown association: #{key}"
238
281
  end
@@ -241,7 +284,10 @@ module ActiveModel
241
284
 
242
285
  # rubocop:disable Metrics/AbcSize
243
286
  def test_conditional_associations
244
- model = ::Model.new(true: true, false: false)
287
+ model = Class.new(::Model) do
288
+ attributes :true, :false
289
+ associations :something
290
+ end.new(true: true, false: false)
245
291
 
246
292
  scenarios = [
247
293
  { options: { if: :true }, included: true },
@@ -264,7 +310,7 @@ module ActiveModel
264
310
 
265
311
  scenarios.each do |s|
266
312
  serializer = Class.new(ActiveModel::Serializer) do
267
- belongs_to :association, s[:options]
313
+ belongs_to :something, s[:options]
268
314
 
269
315
  def true
270
316
  true
@@ -276,7 +322,7 @@ module ActiveModel
276
322
  end
277
323
 
278
324
  hash = serializable(model, serializer: serializer).serializable_hash
279
- assert_equal(s[:included], hash.key?(:association), "Error with #{s[:options]}")
325
+ assert_equal(s[:included], hash.key?(:something), "Error with #{s[:options]}")
280
326
  end
281
327
  end
282
328
 
@@ -290,6 +336,89 @@ module ActiveModel
290
336
  assert_match(/:if should be a Symbol, String or Proc/, exception.message)
291
337
  end
292
338
  end
339
+
340
+ class InheritedSerializerTest < ActiveSupport::TestCase
341
+ class PostSerializer < ActiveModel::Serializer
342
+ belongs_to :author
343
+ has_many :comments
344
+ belongs_to :blog
345
+ end
346
+
347
+ class InheritedPostSerializer < PostSerializer
348
+ belongs_to :author, polymorphic: true
349
+ has_many :comments, key: :reviews
350
+ end
351
+
352
+ class AuthorSerializer < ActiveModel::Serializer
353
+ has_many :posts
354
+ has_many :roles
355
+ has_one :bio
356
+ end
357
+
358
+ class InheritedAuthorSerializer < AuthorSerializer
359
+ has_many :roles, polymorphic: true
360
+ has_one :bio, polymorphic: true
361
+ end
362
+
363
+ def setup
364
+ @author = Author.new(name: 'Steve K.')
365
+ @post = Post.new(title: 'New Post', body: 'Body')
366
+ @post_serializer = PostSerializer.new(@post)
367
+ @author_serializer = AuthorSerializer.new(@author)
368
+ @inherited_post_serializer = InheritedPostSerializer.new(@post)
369
+ @inherited_author_serializer = InheritedAuthorSerializer.new(@author)
370
+ @author_associations = @author_serializer.associations.to_a.sort_by(&:name)
371
+ @inherited_author_associations = @inherited_author_serializer.associations.to_a.sort_by(&:name)
372
+ @post_associations = @post_serializer.associations.to_a
373
+ @inherited_post_associations = @inherited_post_serializer.associations.to_a
374
+ end
375
+
376
+ test 'an author serializer must have [posts,roles,bio] associations' do
377
+ expected = [:posts, :roles, :bio].sort
378
+ result = @author_serializer.associations.map(&:name).sort
379
+ assert_equal(result, expected)
380
+ end
381
+
382
+ test 'a post serializer must have [author,comments,blog] associations' do
383
+ expected = [:author, :comments, :blog].sort
384
+ result = @post_serializer.associations.map(&:name).sort
385
+ assert_equal(result, expected)
386
+ end
387
+
388
+ test 'a serializer inheriting from another serializer can redefine has_many and has_one associations' do
389
+ expected = [:roles, :bio].sort
390
+ result = (@inherited_author_associations.map(&:reflection) - @author_associations.map(&:reflection)).map(&:name)
391
+ assert_equal(result, expected)
392
+ assert_equal [true, false, true], @inherited_author_associations.map(&:polymorphic?)
393
+ assert_equal [false, false, false], @author_associations.map(&:polymorphic?)
394
+ end
395
+
396
+ test 'a serializer inheriting from another serializer can redefine belongs_to associations' do
397
+ assert_equal [:author, :comments, :blog], @post_associations.map(&:name)
398
+ assert_equal [:author, :comments, :blog, :comments], @inherited_post_associations.map(&:name)
399
+
400
+ refute @post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
401
+ assert @inherited_post_associations.detect { |assoc| assoc.name == :author }.polymorphic?
402
+
403
+ refute @post_associations.detect { |assoc| assoc.name == :comments }.key?
404
+ original_comment_assoc, new_comments_assoc = @inherited_post_associations.select { |assoc| assoc.name == :comments }
405
+ refute original_comment_assoc.key?
406
+ assert_equal :reviews, new_comments_assoc.key
407
+
408
+ original_blog = @post_associations.detect { |assoc| assoc.name == :blog }
409
+ inherited_blog = @inherited_post_associations.detect { |assoc| assoc.name == :blog }
410
+ original_parent_serializer = original_blog.lazy_association.association_options.delete(:parent_serializer)
411
+ inherited_parent_serializer = inherited_blog.lazy_association.association_options.delete(:parent_serializer)
412
+ assert_equal PostSerializer, original_parent_serializer.class
413
+ assert_equal InheritedPostSerializer, inherited_parent_serializer.class
414
+ end
415
+
416
+ test 'a serializer inheriting from another serializer can have an additional association with the same name but with different key' do
417
+ expected = [:author, :comments, :blog, :reviews].sort
418
+ result = @inherited_post_serializer.associations.map(&:key).sort
419
+ assert_equal(result, expected)
420
+ end
421
+ end
293
422
  end
294
423
  end
295
424
  end
@@ -22,7 +22,7 @@ module ActiveModel
22
22
  inherited_klass = Class.new(AlternateBlogSerializer)
23
23
  blog_serializer = inherited_klass.new(@blog)
24
24
  adapter = ActiveModelSerializers::Adapter::Attributes.new(blog_serializer)
25
- assert_equal({ :id => 1, :title => 'AMS Hints' }, adapter.serializable_hash)
25
+ assert_equal({ id: 1, title: 'AMS Hints' }, adapter.serializable_hash)
26
26
  end
27
27
 
28
28
  def test_multiple_calls_with_the_same_attribute
@@ -81,7 +81,7 @@ module ActiveModel
81
81
  assert_equal('custom', hash[:blog][:id])
82
82
  end
83
83
 
84
- PostWithVirtualAttribute = Class.new(::Model)
84
+ class PostWithVirtualAttribute < ::Model; attributes :first_name, :last_name end
85
85
  class PostWithVirtualAttributeSerializer < ActiveModel::Serializer
86
86
  attribute :name do
87
87
  "#{object.first_name} #{object.last_name}"
@@ -98,7 +98,9 @@ module ActiveModel
98
98
 
99
99
  # rubocop:disable Metrics/AbcSize
100
100
  def test_conditional_associations
101
- model = ::Model.new(true: true, false: false)
101
+ model = Class.new(::Model) do
102
+ attributes :true, :false, :attribute
103
+ end.new(true: true, false: false)
102
104
 
103
105
  scenarios = [
104
106
  { options: { if: :true }, included: true },
@@ -4,7 +4,7 @@ module ActiveModel
4
4
  class Serializer
5
5
  class AttributesTest < ActiveSupport::TestCase
6
6
  def setup
7
- @profile = Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' })
7
+ @profile = Profile.new(name: 'Name 1', description: 'Description 1', comments: 'Comments 1')
8
8
  @profile_serializer = ProfileSerializer.new(@profile)
9
9
  @comment = Comment.new(id: 1, body: 'ZOMG!!', date: '2015')
10
10
  @serializer_klass = Class.new(CommentSerializer)
@@ -69,9 +69,9 @@ class CachingConfigurationTest < ActiveSupport::TestCase
69
69
  end
70
70
 
71
71
  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
72
+ assert_nil @non_cached_serializer._cache
73
+ assert_nil @non_cached_serializer.cache_store
74
+ assert_nil @non_cached_serializer._cache
75
75
  end
76
76
 
77
77
  test 'the non-cached serializer does not have cache_enabled?' do
@@ -136,9 +136,9 @@ class CachingConfigurationTest < ActiveSupport::TestCase
136
136
  end
137
137
 
138
138
  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
139
+ assert_nil @non_cached_serializer._cache
140
+ assert_nil @non_cached_serializer.cache_store
141
+ assert_nil @non_cached_serializer._cache
142
142
  end
143
143
 
144
144
  test 'the non-cached serializer does not have cache_enabled?' do
@@ -5,7 +5,7 @@ module ActiveModel
5
5
  class FieldsetTest < ActiveSupport::TestCase
6
6
  def test_fieldset_with_hash
7
7
  fieldset = ActiveModel::Serializer::Fieldset.new('post' => %w(id title), 'comment' => ['body'])
8
- expected = { :post => [:id, :title], :comment => [:body] }
8
+ expected = { post: [:id, :title], comment: [:body] }
9
9
 
10
10
  assert_equal(expected, fieldset.fields)
11
11
  end
@@ -15,7 +15,8 @@ module ActiveModel
15
15
  @blog,
16
16
  adapter: :json,
17
17
  serializer: AlternateBlogSerializer,
18
- meta: { total: 10 }).as_json
18
+ meta: { total: 10 }
19
+ ).as_json
19
20
  expected = {
20
21
  blog: {
21
22
  id: 1,
@@ -65,7 +66,8 @@ module ActiveModel
65
66
  @blog,
66
67
  adapter: :attributes,
67
68
  serializer: AlternateBlogSerializer,
68
- meta: { total: 10 }).as_json
69
+ meta: { total: 10 }
70
+ ).as_json
69
71
  expected = {
70
72
  id: 1,
71
73
  title: 'AMS Hints'
@@ -79,7 +81,8 @@ module ActiveModel
79
81
  adapter: :json,
80
82
  serializer: AlternateBlogSerializer,
81
83
  meta: { total: 10 },
82
- meta_key: 'haha_meta').as_json
84
+ meta_key: 'haha_meta'
85
+ ).as_json
83
86
  expected = {
84
87
  blog: {
85
88
  id: 1,
@@ -98,7 +101,8 @@ module ActiveModel
98
101
  adapter: :json_api,
99
102
  serializer: AlternateBlogSerializer,
100
103
  meta: { total: 10 },
101
- meta_key: 'haha_meta').as_json
104
+ meta_key: 'haha_meta'
105
+ ).as_json
102
106
  expected = {
103
107
  data: {
104
108
  id: '1',
@@ -148,7 +152,8 @@ module ActiveModel
148
152
  actual = ActiveModelSerializers::SerializableResource.new(
149
153
  [@blog],
150
154
  adapter: :attributes,
151
- meta: { total: 10 }).as_json
155
+ meta: { total: 10 }
156
+ ).as_json
152
157
  expected = [{
153
158
  id: 1,
154
159
  name: 'AMS Hints',
@@ -170,7 +175,8 @@ module ActiveModel
170
175
  [@blog],
171
176
  adapter: :json,
172
177
  meta: { total: 10 },
173
- meta_key: 'haha_meta').as_json
178
+ meta_key: 'haha_meta'
179
+ ).as_json
174
180
  expected = {
175
181
  blogs: [{
176
182
  id: 1,