active_model_serializers 0.10.5 → 0.10.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +16 -2
- data/README.md +2 -2
- data/Rakefile +1 -30
- data/active_model_serializers.gemspec +1 -1
- data/bin/rubocop +38 -0
- data/docs/general/adapters.md +25 -9
- data/docs/general/getting_started.md +1 -1
- data/docs/general/rendering.md +18 -4
- data/docs/general/serializers.md +21 -2
- data/docs/howto/add_pagination_links.md +1 -1
- data/docs/integrations/ember-and-json-api.md +3 -0
- data/lib/active_model/serializer.rb +252 -74
- data/lib/active_model/serializer/association.rb +51 -14
- data/lib/active_model/serializer/belongs_to_reflection.rb +5 -1
- data/lib/active_model/serializer/concerns/caching.rb +29 -21
- data/lib/active_model/serializer/has_many_reflection.rb +4 -1
- data/lib/active_model/serializer/has_one_reflection.rb +1 -1
- data/lib/active_model/serializer/lazy_association.rb +95 -0
- data/lib/active_model/serializer/reflection.rb +119 -75
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers/adapter/json_api.rb +30 -17
- data/lib/active_model_serializers/adapter/json_api/relationship.rb +38 -9
- data/lib/active_model_serializers/adapter/json_api/resource_identifier.rb +9 -0
- data/lib/active_model_serializers/model.rb +5 -4
- data/lib/tasks/rubocop.rake +53 -0
- data/test/action_controller/adapter_selector_test.rb +2 -2
- data/test/serializers/associations_test.rb +64 -31
- data/test/serializers/reflection_test.rb +427 -0
- metadata +9 -12
- data/lib/active_model/serializer/collection_reflection.rb +0 -7
- data/lib/active_model/serializer/concerns/associations.rb +0 -102
- data/lib/active_model/serializer/concerns/attributes.rb +0 -82
- data/lib/active_model/serializer/concerns/configuration.rb +0 -59
- data/lib/active_model/serializer/concerns/links.rb +0 -35
- data/lib/active_model/serializer/concerns/meta.rb +0 -29
- data/lib/active_model/serializer/concerns/type.rb +0 -25
- data/lib/active_model/serializer/singular_reflection.rb +0 -7
@@ -1,34 +1,71 @@
|
|
1
|
+
require 'active_model/serializer/lazy_association'
|
2
|
+
|
1
3
|
module ActiveModel
|
2
4
|
class Serializer
|
3
5
|
# This class holds all information about serializer's association.
|
4
6
|
#
|
5
|
-
# @
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
# @api private
|
8
|
+
Association = Struct.new(:reflection, :association_options) do
|
9
|
+
attr_reader :lazy_association
|
10
|
+
delegate :object, :include_data?, :virtual_value, :collection?, to: :lazy_association
|
11
|
+
|
12
|
+
def initialize(*)
|
13
|
+
super
|
14
|
+
@lazy_association = LazyAssociation.new(reflection, association_options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [Symbol]
|
18
|
+
delegate :name, to: :reflection
|
19
|
+
|
13
20
|
# @return [Symbol]
|
14
21
|
def key
|
15
|
-
|
22
|
+
reflection_options.fetch(:key, name)
|
16
23
|
end
|
17
24
|
|
18
|
-
# @return [
|
19
|
-
def
|
20
|
-
|
25
|
+
# @return [True,False]
|
26
|
+
def key?
|
27
|
+
reflection_options.key?(:key)
|
21
28
|
end
|
22
29
|
|
23
30
|
# @return [Hash]
|
24
31
|
def links
|
25
|
-
|
32
|
+
reflection_options.fetch(:links) || {}
|
26
33
|
end
|
27
34
|
|
28
35
|
# @return [Hash, nil]
|
36
|
+
# This gets mutated, so cannot use the cached reflection_options
|
29
37
|
def meta
|
30
|
-
options[:meta]
|
38
|
+
reflection.options[:meta]
|
39
|
+
end
|
40
|
+
|
41
|
+
def belongs_to?
|
42
|
+
reflection.foreign_key_on == :self
|
31
43
|
end
|
44
|
+
|
45
|
+
def polymorphic?
|
46
|
+
true == reflection_options[:polymorphic]
|
47
|
+
end
|
48
|
+
|
49
|
+
# @api private
|
50
|
+
def serializable_hash(adapter_options, adapter_instance)
|
51
|
+
association_serializer = lazy_association.serializer
|
52
|
+
return virtual_value if virtual_value
|
53
|
+
association_object = association_serializer && association_serializer.object
|
54
|
+
return unless association_object
|
55
|
+
|
56
|
+
serialization = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)
|
57
|
+
|
58
|
+
if polymorphic? && serialization
|
59
|
+
polymorphic_type = association_object.class.name.underscore
|
60
|
+
serialization = { type: polymorphic_type, polymorphic_type.to_sym => serialization }
|
61
|
+
end
|
62
|
+
|
63
|
+
serialization
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
delegate :reflection_options, to: :lazy_association
|
32
69
|
end
|
33
70
|
end
|
34
71
|
end
|
@@ -40,9 +40,9 @@ module ActiveModel
|
|
40
40
|
|
41
41
|
module ClassMethods
|
42
42
|
def inherited(base)
|
43
|
-
super
|
44
43
|
caller_line = caller[1]
|
45
44
|
base._cache_digest_file_path = caller_line
|
45
|
+
super
|
46
46
|
end
|
47
47
|
|
48
48
|
def _cache_digest
|
@@ -68,6 +68,18 @@ module ActiveModel
|
|
68
68
|
_cache_options && _cache_options[:skip_digest]
|
69
69
|
end
|
70
70
|
|
71
|
+
# @api private
|
72
|
+
# maps attribute value to explicit key name
|
73
|
+
# @see Serializer::attribute
|
74
|
+
# @see Serializer::fragmented_attributes
|
75
|
+
def _attributes_keys
|
76
|
+
_attributes_data
|
77
|
+
.each_with_object({}) do |(key, attr), hash|
|
78
|
+
next if key == attr.name
|
79
|
+
hash[attr.name] = { key: key }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
71
83
|
def fragmented_attributes
|
72
84
|
cached = _cache_only ? _cache_only : _attributes - _cache_except
|
73
85
|
cached = cached.map! { |field| _attributes_keys.fetch(field, field) }
|
@@ -158,6 +170,7 @@ module ActiveModel
|
|
158
170
|
|
159
171
|
# Read cache from cache_store
|
160
172
|
# @return [Hash]
|
173
|
+
# Used in CollectionSerializer to set :cached_attributes
|
161
174
|
def cache_read_multi(collection_serializer, adapter_instance, include_directive)
|
162
175
|
return {} if ActiveModelSerializers.config.cache_store.blank?
|
163
176
|
|
@@ -180,12 +193,14 @@ module ActiveModel
|
|
180
193
|
cache_keys << object_cache_key(serializer, adapter_instance)
|
181
194
|
|
182
195
|
serializer.associations(include_directive).each do |association|
|
183
|
-
|
184
|
-
|
196
|
+
# TODO(BF): Process relationship without evaluating lazy_association
|
197
|
+
association_serializer = association.lazy_association.serializer
|
198
|
+
if association_serializer.respond_to?(:each)
|
199
|
+
association_serializer.each do |sub_serializer|
|
185
200
|
cache_keys << object_cache_key(sub_serializer, adapter_instance)
|
186
201
|
end
|
187
202
|
else
|
188
|
-
cache_keys << object_cache_key(
|
203
|
+
cache_keys << object_cache_key(association_serializer, adapter_instance)
|
189
204
|
end
|
190
205
|
end
|
191
206
|
end
|
@@ -203,23 +218,18 @@ module ActiveModel
|
|
203
218
|
|
204
219
|
### INSTANCE METHODS
|
205
220
|
def fetch_attributes(fields, cached_attributes, adapter_instance)
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
attributes(fields, true)
|
211
|
-
end
|
221
|
+
key = cache_key(adapter_instance)
|
222
|
+
cached_attributes.fetch(key) do
|
223
|
+
fetch(adapter_instance, serializer_class._cache_options, key) do
|
224
|
+
attributes(fields, true)
|
212
225
|
end
|
213
|
-
elsif serializer_class.fragment_cache_enabled?
|
214
|
-
fetch_attributes_fragment(adapter_instance, cached_attributes)
|
215
|
-
else
|
216
|
-
attributes(fields, true)
|
217
226
|
end
|
218
227
|
end
|
219
228
|
|
220
|
-
def fetch(adapter_instance, cache_options = serializer_class._cache_options)
|
229
|
+
def fetch(adapter_instance, cache_options = serializer_class._cache_options, key = nil)
|
221
230
|
if serializer_class.cache_store
|
222
|
-
|
231
|
+
key ||= cache_key(adapter_instance)
|
232
|
+
serializer_class.cache_store.fetch(key, cache_options) do
|
223
233
|
yield
|
224
234
|
end
|
225
235
|
else
|
@@ -230,7 +240,6 @@ module ActiveModel
|
|
230
240
|
# 1. Determine cached fields from serializer class options
|
231
241
|
# 2. Get non_cached_fields and fetch cache_fields
|
232
242
|
# 3. Merge the two hashes using adapter_instance#fragment_cache
|
233
|
-
# rubocop:disable Metrics/AbcSize
|
234
243
|
def fetch_attributes_fragment(adapter_instance, cached_attributes = {})
|
235
244
|
serializer_class._cache_options ||= {}
|
236
245
|
serializer_class._cache_options[:key] = serializer_class._cache_key if serializer_class._cache_key
|
@@ -239,22 +248,21 @@ module ActiveModel
|
|
239
248
|
non_cached_fields = fields[:non_cached].dup
|
240
249
|
non_cached_hash = attributes(non_cached_fields, true)
|
241
250
|
include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys)
|
242
|
-
non_cached_hash.merge!
|
251
|
+
non_cached_hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance)
|
243
252
|
|
244
253
|
cached_fields = fields[:cached].dup
|
245
254
|
key = cache_key(adapter_instance)
|
246
255
|
cached_hash =
|
247
256
|
cached_attributes.fetch(key) do
|
248
|
-
|
257
|
+
fetch(adapter_instance, serializer_class._cache_options, key) do
|
249
258
|
hash = attributes(cached_fields, true)
|
250
259
|
include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys)
|
251
|
-
hash.merge!
|
260
|
+
hash.merge! associations_hash({}, { include_directive: include_directive }, adapter_instance)
|
252
261
|
end
|
253
262
|
end
|
254
263
|
# Merge both results
|
255
264
|
adapter_instance.fragment_cache(cached_hash, non_cached_hash)
|
256
265
|
end
|
257
|
-
# rubocop:enable Metrics/AbcSize
|
258
266
|
|
259
267
|
def cache_key(adapter_instance)
|
260
268
|
return @cache_key if defined?(@cache_key)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
class Serializer
|
3
|
+
# @api private
|
4
|
+
LazyAssociation = Struct.new(:reflection, :association_options) do
|
5
|
+
REFLECTION_OPTIONS = %i(key links polymorphic meta serializer virtual_value namespace).freeze
|
6
|
+
|
7
|
+
delegate :collection?, to: :reflection
|
8
|
+
|
9
|
+
def reflection_options
|
10
|
+
@reflection_options ||= reflection.options.dup.reject { |k, _| !REFLECTION_OPTIONS.include?(k) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def object
|
14
|
+
@object ||= reflection.value(
|
15
|
+
association_options.fetch(:parent_serializer),
|
16
|
+
association_options.fetch(:include_slice)
|
17
|
+
)
|
18
|
+
end
|
19
|
+
alias_method :eval_reflection_block, :object
|
20
|
+
|
21
|
+
def include_data?
|
22
|
+
eval_reflection_block if reflection.block
|
23
|
+
reflection.include_data?(
|
24
|
+
association_options.fetch(:include_slice)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [ActiveModel::Serializer, nil]
|
29
|
+
def serializer
|
30
|
+
return @serializer if defined?(@serializer)
|
31
|
+
if serializer_class
|
32
|
+
serialize_object!(object)
|
33
|
+
elsif !object.nil? && !object.instance_of?(Object)
|
34
|
+
cached_result[:virtual_value] = object
|
35
|
+
end
|
36
|
+
@serializer = cached_result[:serializer]
|
37
|
+
end
|
38
|
+
|
39
|
+
def virtual_value
|
40
|
+
cached_result[:virtual_value] || reflection_options[:virtual_value]
|
41
|
+
end
|
42
|
+
|
43
|
+
def serializer_class
|
44
|
+
return @serializer_class if defined?(@serializer_class)
|
45
|
+
serializer_for_options = { namespace: namespace }
|
46
|
+
serializer_for_options[:serializer] = reflection_options[:serializer] if reflection_options.key?(:serializer)
|
47
|
+
@serializer_class = association_options.fetch(:parent_serializer).class.serializer_for(object, serializer_for_options)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def cached_result
|
53
|
+
@cached_result ||= {}
|
54
|
+
end
|
55
|
+
|
56
|
+
def serialize_object!(object)
|
57
|
+
if collection?
|
58
|
+
if (serializer = instantiate_collection_serializer(object)).nil?
|
59
|
+
# BUG: per #2027, JSON API resource relationships are only id and type, and hence either
|
60
|
+
# *require* a serializer or we need to be a little clever about figuring out the id/type.
|
61
|
+
# In either case, returning the raw virtual value will almost always be incorrect.
|
62
|
+
#
|
63
|
+
# Should be reflection_options[:virtual_value] or adapter needs to figure out what to do
|
64
|
+
# with an object that is non-nil and has no defined serializer.
|
65
|
+
cached_result[:virtual_value] = object.try(:as_json) || object
|
66
|
+
else
|
67
|
+
cached_result[:serializer] = serializer
|
68
|
+
end
|
69
|
+
else
|
70
|
+
cached_result[:serializer] = instantiate_serializer(object)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def instantiate_serializer(object)
|
75
|
+
serializer_options = association_options.fetch(:parent_serializer_options).except(:serializer)
|
76
|
+
serializer_options[:serializer_context_class] = association_options.fetch(:parent_serializer).class
|
77
|
+
serializer = reflection_options.fetch(:serializer, nil)
|
78
|
+
serializer_options[:serializer] = serializer if serializer
|
79
|
+
serializer_class.new(object, serializer_options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def instantiate_collection_serializer(object)
|
83
|
+
serializer = catch(:no_serializer) do
|
84
|
+
instantiate_serializer(object)
|
85
|
+
end
|
86
|
+
serializer
|
87
|
+
end
|
88
|
+
|
89
|
+
def namespace
|
90
|
+
reflection_options[:namespace] ||
|
91
|
+
association_options.fetch(:parent_serializer_options)[:namespace]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_model/serializer/field'
|
2
|
+
require 'active_model/serializer/association'
|
2
3
|
|
3
4
|
module ActiveModel
|
4
5
|
class Serializer
|
@@ -8,12 +9,26 @@ module ActiveModel
|
|
8
9
|
# @example
|
9
10
|
# class PostSerializer < ActiveModel::Serializer
|
10
11
|
# has_one :author, serializer: AuthorSerializer
|
12
|
+
# belongs_to :boss, type: :users, foreign_key: :boss_id
|
11
13
|
# has_many :comments
|
12
14
|
# has_many :comments, key: :last_comments do
|
13
15
|
# object.comments.last(1)
|
14
16
|
# end
|
15
17
|
# has_many :secret_meta_data, if: :is_admin?
|
16
18
|
#
|
19
|
+
# has_one :blog do |serializer|
|
20
|
+
# meta count: object.roles.count
|
21
|
+
# serializer.cached_blog
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# private
|
25
|
+
#
|
26
|
+
# def cached_blog
|
27
|
+
# cache_store.fetch("cached_blog:#{object.updated_at}") do
|
28
|
+
# Blog.find(object.blog_id)
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
#
|
17
32
|
# def is_admin?
|
18
33
|
# current_user.admin?
|
19
34
|
# end
|
@@ -23,52 +38,118 @@ module ActiveModel
|
|
23
38
|
# 1) as 'comments' and named 'comments'.
|
24
39
|
# 2) as 'object.comments.last(1)' and named 'last_comments'.
|
25
40
|
#
|
26
|
-
# PostSerializer._reflections
|
27
|
-
# #
|
28
|
-
# # HasOneReflection.new(:author, serializer: AuthorSerializer),
|
29
|
-
# # HasManyReflection.new(:comments)
|
30
|
-
# # HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
|
31
|
-
# # HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
|
32
|
-
# #
|
41
|
+
# PostSerializer._reflections # =>
|
42
|
+
# # {
|
43
|
+
# # author: HasOneReflection.new(:author, serializer: AuthorSerializer),
|
44
|
+
# # comments: HasManyReflection.new(:comments)
|
45
|
+
# # last_comments: HasManyReflection.new(:comments, { key: :last_comments }, #<Block>)
|
46
|
+
# # secret_meta_data: HasManyReflection.new(:secret_meta_data, { if: :is_admin? })
|
47
|
+
# # }
|
33
48
|
#
|
34
49
|
# So you can inspect reflections in your Adapters.
|
35
|
-
#
|
36
50
|
class Reflection < Field
|
51
|
+
attr_reader :foreign_key, :type
|
52
|
+
|
37
53
|
def initialize(*)
|
38
54
|
super
|
39
|
-
|
40
|
-
|
41
|
-
|
55
|
+
options[:links] = {}
|
56
|
+
options[:include_data_setting] = Serializer.config.include_data_default
|
57
|
+
options[:meta] = nil
|
58
|
+
@type = options.fetch(:type) do
|
59
|
+
class_name = options.fetch(:class_name, name.to_s.camelize.singularize)
|
60
|
+
class_name.underscore.pluralize.to_sym
|
61
|
+
end
|
62
|
+
@foreign_key = options.fetch(:foreign_key) do
|
63
|
+
if collection?
|
64
|
+
"#{name.to_s.singularize}_ids".to_sym
|
65
|
+
else
|
66
|
+
"#{name}_id".to_sym
|
67
|
+
end
|
68
|
+
end
|
42
69
|
end
|
43
70
|
|
44
|
-
|
45
|
-
|
71
|
+
# @api public
|
72
|
+
# @example
|
73
|
+
# has_one :blog do
|
74
|
+
# include_data false
|
75
|
+
# link :self, 'a link'
|
76
|
+
# link :related, 'another link'
|
77
|
+
# link :self, '//example.com/link_author/relationships/bio'
|
78
|
+
# id = object.profile.id
|
79
|
+
# link :related do
|
80
|
+
# "//example.com/profiles/#{id}" if id != 123
|
81
|
+
# end
|
82
|
+
# link :related do
|
83
|
+
# ids = object.likes.map(&:id).join(',')
|
84
|
+
# href "//example.com/likes/#{ids}"
|
85
|
+
# meta ids: ids
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
def link(name, value = nil)
|
89
|
+
options[:links][name] = block_given? ? Proc.new : value
|
46
90
|
:nil
|
47
91
|
end
|
48
92
|
|
49
|
-
|
50
|
-
|
93
|
+
# @api public
|
94
|
+
# @example
|
95
|
+
# has_one :blog do
|
96
|
+
# include_data false
|
97
|
+
# meta(id: object.blog.id)
|
98
|
+
# meta liked: object.likes.any?
|
99
|
+
# link :self do
|
100
|
+
# href object.blog.id.to_s
|
101
|
+
# meta(id: object.blog.id)
|
102
|
+
# end
|
103
|
+
def meta(value = nil)
|
104
|
+
options[:meta] = block_given? ? Proc.new : value
|
51
105
|
:nil
|
52
106
|
end
|
53
107
|
|
108
|
+
# @api public
|
109
|
+
# @example
|
110
|
+
# has_one :blog do
|
111
|
+
# include_data false
|
112
|
+
# link :self, 'a link'
|
113
|
+
# link :related, 'another link'
|
114
|
+
# end
|
115
|
+
#
|
116
|
+
# has_one :blog do
|
117
|
+
# include_data false
|
118
|
+
# link :self, 'a link'
|
119
|
+
# link :related, 'another link'
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# belongs_to :reviewer do
|
123
|
+
# meta name: 'Dan Brown'
|
124
|
+
# include_data true
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
# has_many :tags, serializer: TagSerializer do
|
128
|
+
# link :self, '//example.com/link_author/relationships/tags'
|
129
|
+
# include_data :if_sideloaded
|
130
|
+
# end
|
54
131
|
def include_data(value = true)
|
55
|
-
|
132
|
+
options[:include_data_setting] = value
|
56
133
|
:nil
|
57
134
|
end
|
58
135
|
|
136
|
+
def collection?
|
137
|
+
false
|
138
|
+
end
|
139
|
+
|
140
|
+
def include_data?(include_slice)
|
141
|
+
include_data_setting = options[:include_data_setting]
|
142
|
+
case include_data_setting
|
143
|
+
when :if_sideloaded then include_slice.key?(name)
|
144
|
+
when true then true
|
145
|
+
when false then false
|
146
|
+
else fail ArgumentError, "Unknown include_data_setting '#{include_data_setting.inspect}'"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
59
150
|
# @param serializer [ActiveModel::Serializer]
|
60
151
|
# @yield [ActiveModel::Serializer]
|
61
152
|
# @return [:nil, associated resource or resource collection]
|
62
|
-
# @example
|
63
|
-
# has_one :blog do |serializer|
|
64
|
-
# serializer.cached_blog
|
65
|
-
# end
|
66
|
-
#
|
67
|
-
# def cached_blog
|
68
|
-
# cache_store.fetch("cached_blog:#{object.updated_at}") do
|
69
|
-
# Blog.find(object.blog_id)
|
70
|
-
# end
|
71
|
-
# end
|
72
153
|
def value(serializer, include_slice)
|
73
154
|
@object = serializer.object
|
74
155
|
@scope = serializer.scope
|
@@ -83,6 +164,11 @@ module ActiveModel
|
|
83
164
|
end
|
84
165
|
end
|
85
166
|
|
167
|
+
# @api private
|
168
|
+
def foreign_key_on
|
169
|
+
:related
|
170
|
+
end
|
171
|
+
|
86
172
|
# Build association. This method is used internally to
|
87
173
|
# build serializer's association by its reflection.
|
88
174
|
#
|
@@ -103,61 +189,19 @@ module ActiveModel
|
|
103
189
|
# comments_reflection.build_association(post_serializer, foo: 'bar')
|
104
190
|
#
|
105
191
|
# @api private
|
106
|
-
#
|
107
192
|
def build_association(parent_serializer, parent_serializer_options, include_slice = {})
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
serializer_class = parent_serializer.class.serializer_for(association_value, reflection_options)
|
115
|
-
reflection_options[:include_data] = include_data?(include_slice)
|
116
|
-
reflection_options[:links] = @_links
|
117
|
-
reflection_options[:meta] = @_meta
|
118
|
-
|
119
|
-
if serializer_class
|
120
|
-
serializer = catch(:no_serializer) do
|
121
|
-
serializer_class.new(
|
122
|
-
association_value,
|
123
|
-
serializer_options(parent_serializer, parent_serializer_options, reflection_options)
|
124
|
-
)
|
125
|
-
end
|
126
|
-
if serializer.nil?
|
127
|
-
reflection_options[:virtual_value] = association_value.try(:as_json) || association_value
|
128
|
-
else
|
129
|
-
reflection_options[:serializer] = serializer
|
130
|
-
end
|
131
|
-
elsif !association_value.nil? && !association_value.instance_of?(Object)
|
132
|
-
reflection_options[:virtual_value] = association_value
|
133
|
-
end
|
134
|
-
|
135
|
-
block = nil
|
136
|
-
Association.new(name, reflection_options, block)
|
193
|
+
association_options = {
|
194
|
+
parent_serializer: parent_serializer,
|
195
|
+
parent_serializer_options: parent_serializer_options,
|
196
|
+
include_slice: include_slice
|
197
|
+
}
|
198
|
+
Association.new(self, association_options)
|
137
199
|
end
|
138
200
|
|
139
201
|
protected
|
140
202
|
|
203
|
+
# used in instance exec
|
141
204
|
attr_accessor :object, :scope
|
142
|
-
|
143
|
-
private
|
144
|
-
|
145
|
-
def include_data?(include_slice)
|
146
|
-
if @_include_data == :if_sideloaded
|
147
|
-
include_slice.key?(name)
|
148
|
-
else
|
149
|
-
@_include_data
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
def serializer_options(parent_serializer, parent_serializer_options, reflection_options)
|
154
|
-
serializer = reflection_options.fetch(:serializer, nil)
|
155
|
-
|
156
|
-
serializer_options = parent_serializer_options.except(:serializer)
|
157
|
-
serializer_options[:serializer] = serializer if serializer
|
158
|
-
serializer_options[:serializer_context_class] = parent_serializer.class
|
159
|
-
serializer_options
|
160
|
-
end
|
161
205
|
end
|
162
206
|
end
|
163
207
|
end
|