-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
collection_serializer.rb
85 lines (73 loc) · 3.29 KB
/
collection_serializer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
module ActiveModel
class Serializer
class CollectionSerializer
include Enumerable
delegate :each, to: :@serializers
attr_reader :object, :root
def initialize(resources, options = {})
@object = resources
@options = options
@root = options[:root]
@serializers = serializers_from_resources
end
def success?
true
end
# @api private
def serializable_hash(adapter_options, options, adapter_instance)
include_directive = ActiveModel::Serializer.include_directive_from_options(adapter_options)
adapter_options[:cached_attributes] ||= ActiveModel::Serializer.cache_read_multi(self, adapter_instance, include_directive)
adapter_opts = adapter_options.merge(include_directive: include_directive)
serializers.map do |serializer|
serializer.serializable_hash(adapter_opts, options, adapter_instance)
end
end
# TODO: unify naming of root, json_key, and _type. Right now, a serializer's
# json_key comes from the root option or the object's model name, by default.
# But, if a dev defines a custom `json_key` method with an explicit value,
# we have no simple way to know that it is safe to call that instance method.
# (which is really a class property at this point, anyhow).
# rubocop:disable Metrics/CyclomaticComplexity
# Disabling cop since it's good to highlight the complexity of this method by
# including all the logic right here.
def json_key
return root if root
# 1. get from options[:serializer] for empty resource collection
key = object.empty? &&
(explicit_serializer_class = options[:serializer]) &&
explicit_serializer_class._type
# 2. get from first serializer instance in collection
key ||= (serializer = serializers.first) && serializer.json_key
# 3. get from collection name, if a named collection
key ||= object.respond_to?(:name) ? object.name && object.name.underscore : nil
# 4. key may be nil for empty collection and no serializer option
key && key.pluralize
end
# rubocop:enable Metrics/CyclomaticComplexity
def paginated?
ActiveModelSerializers.config.jsonapi_pagination_links_enabled &&
object.respond_to?(:current_page) &&
object.respond_to?(:total_pages) &&
object.respond_to?(:size)
end
protected
attr_reader :serializers, :options
private
def serializers_from_resources
serializer_context_class = options.fetch(:serializer_context_class, ActiveModel::Serializer)
object.map do |resource|
serializer_from_resource(resource, serializer_context_class, options)
end
end
def serializer_from_resource(resource, serializer_context_class, options)
serializer_class = options.fetch(:serializer) { serializer_context_class.serializer_for(resource) }
if serializer_class.nil?
ActiveModelSerializers.logger.debug "No serializer found for resource: #{resource.inspect}"
throw :no_serializer
else
serializer_class.new(resource, options.except(:serializer))
end
end
end
end
end