Skip to content

Commit e5c4ac1

Browse files
committed
Include Serializer._type in collection serializer json_key cascade
1 parent 504cceb commit e5c4ac1

File tree

5 files changed

+27
-31
lines changed

5 files changed

+27
-31
lines changed

Diff for: CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
Breaking changes:
44

55
Features:
6+
- [#1618](https://github.com/rails-api/active_model_serializers/issues/1618) Get collection root key for
7+
empty collection from explicit serializer option, when possible. (@bf4)
68
- [#1574](https://github.com/rails-api/active_model_serializers/pull/1574) Provide key translation. (@remear)
79
- [#1494](https://github.com/rails-api/active_model_serializers/pull/1494) Make serializers serializalbe
810
(using the Attributes adapter by default). (@bf4)

Diff for: lib/active_model/serializer.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def as_json(adapter_opts = nil)
182182

183183
# Used by adapter as resource root.
184184
def json_key
185-
root || object.class.model_name.to_s.underscore
185+
root || _type || object.class.model_name.to_s.underscore
186186
end
187187

188188
def read_attribute_for_serialization(attr)

Diff for: lib/active_model/serializer/collection_serializer.rb

+20-24
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,10 @@ class CollectionSerializer
88
attr_reader :object, :root
99

1010
def initialize(resources, options = {})
11-
@root = options[:root]
12-
@object = resources
13-
11+
@object = resources
12+
@options = options
13+
@root = options[:root]
1414
serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer)
15-
16-
if resources.blank? && options[:serializer]
17-
@each_serializer = options[:serializer]
18-
end
19-
2015
@serializers = resources.map do |resource|
2116
serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) }
2217

@@ -32,8 +27,23 @@ def success?
3227
true
3328
end
3429

30+
# TODO: unify naming of root, json_key, and _type. Right now, a serializer's
31+
# json_key comes from the root option or the object's model name, by default.
32+
# But, if a dev defines a custom `json_key` method with an explicit value,
33+
# we have no simple way to know that it is safe to call that instance method.
34+
# (which is really a class property at this point, anyhow).
3535
def json_key
36-
root || derived_root || guess_root || default_root
36+
return root if root
37+
# 1. get from options[:serializer] for empty resource collection
38+
key = object.empty? &&
39+
(explicit_serializer_class = options[:serializer]) &&
40+
explicit_serializer_class._type
41+
# 2. get from first serializer instance in collection
42+
key ||= (serializer = serializers.first) && serializer.json_key
43+
# 3. get from collection name, if a named collection
44+
key ||= object.respond_to?(:name) ? object.name && object.name.underscore : nil
45+
# 4. key may be nil for empty collection and no serializer option
46+
key && key.pluralize
3747
end
3848

3949
def paginated?
@@ -44,21 +54,7 @@ def paginated?
4454

4555
protected
4656

47-
attr_reader :serializers
48-
49-
private
50-
51-
def derived_root
52-
serializers.first.try(:json_key).try(:pluralize)
53-
end
54-
55-
def default_root
56-
object.try(:name).try(:underscore).try(:pluralize)
57-
end
58-
59-
def guess_root
60-
@each_serializer.try(:allocate).try(:json_key).try(:pluralize)
61-
end
57+
attr_reader :serializers, :options
6258
end
6359
end
6460
end

Diff for: test/collection_serializer_test.rb

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
module ActiveModel
44
class Serializer
55
class CollectionSerializerTest < ActiveSupport::TestCase
6+
MessagesSerializer = Class.new(ActiveModel::Serializer) do
7+
type 'messages'
8+
end
9+
610
def setup
711
@comment = Comment.new
812
@post = Post.new

Diff for: test/fixtures/poro.rb

-6
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,6 @@ def json_key
183183
end
184184
end
185185

186-
MessagesSerializer = Class.new(ActiveModel::Serializer) do
187-
def json_key
188-
'messages'
189-
end
190-
end
191-
192186
AlternateBlogSerializer = Class.new(ActiveModel::Serializer) do
193187
attribute :id
194188
attribute :name, key: :title

0 commit comments

Comments
 (0)