active_model_serializers 0.9.0 → 0.9.8
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +113 -0
- data/README.md +112 -19
- data/lib/action_controller/serialization.rb +35 -8
- data/lib/action_controller/serialization_test_case.rb +4 -4
- data/lib/active_model/array_serializer.rb +13 -10
- data/lib/active_model/default_serializer.rb +2 -6
- data/lib/active_model/serializable.rb +30 -11
- data/lib/active_model/serializable/utils.rb +16 -0
- data/lib/active_model/serializer.rb +90 -40
- data/lib/active_model/serializer/{associations.rb → association.rb} +8 -52
- data/lib/active_model/serializer/association/has_many.rb +39 -0
- data/lib/active_model/serializer/association/has_one.rb +25 -0
- data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +1 -1
- data/lib/active_model/serializer/railtie.rb +12 -0
- data/lib/active_model/serializer/version.rb +1 -1
- data/lib/active_model_serializers.rb +1 -1
- data/lib/active_model_serializers/model/caching.rb +25 -0
- data/test/benchmark/app.rb +60 -0
- data/test/benchmark/benchmarking_support.rb +67 -0
- data/test/benchmark/bm_active_record.rb +41 -0
- data/test/benchmark/setup.rb +75 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_6eqewtfgrhitvq5gqm25 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_8083sx03hu72pxz1a4d0 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_fyz2gsml4z0ph9kpoy1c +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_hjry5rc32imd42oxoi48 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_m8fpoz2cvt3g9agz0bs3 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_p92m2drnj1i568u3sta0 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_qg52tpca3uesdfguee9i +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_s15t1a6mvxe0z7vjv790 +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_timers_x8kal3d17nfds6vp4kcj +0 -0
- data/test/benchmark/tmp/miniprofiler/mp_views_127.0.0.1 +0 -0
- data/test/fixtures/active_record.rb +4 -0
- data/test/fixtures/poro.rb +149 -1
- data/test/fixtures/template.html.erb +1 -0
- data/test/integration/action_controller/namespaced_serialization_test.rb +105 -0
- data/test/integration/action_controller/serialization_test.rb +5 -5
- data/test/integration/action_controller/serialization_test_case_test.rb +10 -0
- data/test/integration/active_record/active_record_test.rb +19 -2
- data/test/test_app.rb +3 -0
- data/test/tmp/app/assets/javascripts/accounts.js +2 -0
- data/test/tmp/app/assets/stylesheets/accounts.css +4 -0
- data/test/tmp/app/controllers/accounts_controller.rb +2 -0
- data/test/tmp/app/helpers/accounts_helper.rb +2 -0
- data/test/tmp/app/serializers/account_serializer.rb +3 -0
- data/test/tmp/config/routes.rb +1 -0
- data/test/unit/active_model/array_serializer/options_test.rb +16 -0
- data/test/unit/active_model/array_serializer/serialization_test.rb +18 -1
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +15 -0
- data/test/unit/active_model/serializer/associations_test.rb +30 -0
- data/test/unit/active_model/serializer/attributes_test.rb +16 -0
- data/test/unit/active_model/serializer/config_test.rb +3 -0
- data/test/unit/active_model/serializer/has_many_polymorphic_test.rb +189 -0
- data/test/unit/active_model/serializer/has_many_test.rb +52 -17
- data/test/unit/active_model/serializer/has_one_and_has_many_test.rb +27 -0
- data/test/unit/active_model/serializer/has_one_polymorphic_test.rb +196 -0
- data/test/unit/active_model/serializer/has_one_test.rb +46 -0
- data/test/unit/active_model/serializer/options_test.rb +27 -0
- data/test/unit/active_model/serializer/url_helpers_test.rb +35 -0
- data/test/unit/active_model/serilizable_test.rb +50 -0
- metadata +98 -25
@@ -15,15 +15,18 @@ module ActiveModel
|
|
15
15
|
@object = object
|
16
16
|
@scope = options[:scope]
|
17
17
|
@root = options.fetch(:root, self.class._root)
|
18
|
+
@polymorphic = options.fetch(:polymorphic, false)
|
18
19
|
@meta_key = options[:meta_key] || :meta
|
19
20
|
@meta = options[@meta_key]
|
20
21
|
@each_serializer = options[:each_serializer]
|
21
22
|
@resource_name = options[:resource_name]
|
22
23
|
@only = options[:only] ? Array(options[:only]) : nil
|
23
24
|
@except = options[:except] ? Array(options[:except]) : nil
|
25
|
+
@context = options[:context]
|
26
|
+
@namespace = options[:namespace]
|
24
27
|
@key_format = options[:key_format] || options[:each_serializer].try(:key_format)
|
25
28
|
end
|
26
|
-
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format
|
29
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context
|
27
30
|
|
28
31
|
def json_key
|
29
32
|
key = root.nil? ? @resource_name : root
|
@@ -32,13 +35,13 @@ module ActiveModel
|
|
32
35
|
end
|
33
36
|
|
34
37
|
def serializer_for(item)
|
35
|
-
serializer_class = @each_serializer || Serializer.serializer_for(item) || DefaultSerializer
|
36
|
-
serializer_class.new(item, scope: scope, key_format: key_format, only: @only, except: @except)
|
38
|
+
serializer_class = @each_serializer || Serializer.serializer_for(item, namespace: @namespace) || DefaultSerializer
|
39
|
+
serializer_class.new(item, scope: scope, key_format: key_format, context: @context, only: @only, except: @except, polymorphic: @polymorphic, namespace: @namespace)
|
37
40
|
end
|
38
41
|
|
39
|
-
def serializable_object
|
42
|
+
def serializable_object(options={})
|
40
43
|
@object.map do |item|
|
41
|
-
serializer_for(item).
|
44
|
+
serializer_for(item).serializable_object_with_notification(options)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
alias_method :serializable_array, :serializable_object
|
@@ -49,7 +52,11 @@ module ActiveModel
|
|
49
52
|
next if !objects || objects.flatten.empty?
|
50
53
|
|
51
54
|
if hash.has_key?(type)
|
52
|
-
hash[type]
|
55
|
+
case hash[type] when Hash
|
56
|
+
hash[type].deep_merge!(objects){ |key, old, new| (Array(old) + Array(new)).uniq }
|
57
|
+
else
|
58
|
+
hash[type].concat(objects).uniq!
|
59
|
+
end
|
53
60
|
else
|
54
61
|
hash[type] = objects
|
55
62
|
end
|
@@ -57,9 +64,5 @@ module ActiveModel
|
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
60
|
-
private
|
61
|
-
def instrumentation_keys
|
62
|
-
[:object, :scope, :root, :meta_key, :meta, :each_serializer, :resource_name, :key_format]
|
63
|
-
end
|
64
67
|
end
|
65
68
|
end
|
@@ -15,18 +15,14 @@ module ActiveModel
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def as_json(options={})
|
18
|
-
instrument
|
18
|
+
instrument do
|
19
19
|
return [] if @object.nil? && @wrap_in_array
|
20
20
|
hash = @object.as_json
|
21
21
|
@wrap_in_array ? [hash] : hash
|
22
22
|
end
|
23
23
|
end
|
24
|
+
|
24
25
|
alias serializable_hash as_json
|
25
26
|
alias serializable_object as_json
|
26
|
-
|
27
|
-
private
|
28
|
-
def instrumentation_keys
|
29
|
-
[:object, :wrap_in_array]
|
30
|
-
end
|
31
27
|
end
|
32
28
|
end
|
@@ -1,17 +1,29 @@
|
|
1
|
+
require 'active_model/serializable/utils'
|
2
|
+
|
1
3
|
module ActiveModel
|
2
4
|
module Serializable
|
5
|
+
INSTRUMENTATION_KEY = '!serialize.active_model_serializers'.freeze
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend Utils
|
9
|
+
end
|
10
|
+
|
3
11
|
def as_json(options={})
|
4
|
-
instrument
|
12
|
+
instrument do
|
5
13
|
if root = options.fetch(:root, json_key)
|
6
|
-
hash = { root => serializable_object }
|
14
|
+
hash = { root => serializable_object(options) }
|
7
15
|
hash.merge!(serializable_data)
|
8
16
|
hash
|
9
17
|
else
|
10
|
-
serializable_object
|
18
|
+
serializable_object(options)
|
11
19
|
end
|
12
20
|
end
|
13
21
|
end
|
14
22
|
|
23
|
+
def serializable_object_with_notification(options={})
|
24
|
+
instrument { serializable_object(options) }
|
25
|
+
end
|
26
|
+
|
15
27
|
def serializable_data
|
16
28
|
embedded_in_root_associations.tap do |hash|
|
17
29
|
if respond_to?(:meta) && meta
|
@@ -20,21 +32,28 @@ module ActiveModel
|
|
20
32
|
end
|
21
33
|
end
|
22
34
|
|
35
|
+
def namespace
|
36
|
+
if module_name = get_namespace
|
37
|
+
Serializer.serializers_cache.fetch_or_store(module_name) do
|
38
|
+
Utils._const_get(module_name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
23
43
|
def embedded_in_root_associations
|
24
44
|
{}
|
25
45
|
end
|
26
46
|
|
27
47
|
private
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
ActiveSupport::Notifications.instrument("#{action}.active_model_serializers", payload, &block)
|
48
|
+
|
49
|
+
def get_namespace
|
50
|
+
modules = self.class.name.split('::')
|
51
|
+
modules[0..-2].join('::') if modules.size > 1
|
34
52
|
end
|
35
53
|
|
36
|
-
def
|
37
|
-
|
54
|
+
def instrument(&block)
|
55
|
+
payload = { serializer: self.class.name }
|
56
|
+
ActiveSupport::Notifications.instrument(INSTRUMENTATION_KEY, payload, &block)
|
38
57
|
end
|
39
58
|
end
|
40
59
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Serializable
|
3
|
+
module Utils
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def _const_get(const)
|
7
|
+
begin
|
8
|
+
method = RUBY_VERSION >= '2.0' ? :const_get : :qualified_const_get
|
9
|
+
Object.send method, const
|
10
|
+
rescue NameError
|
11
|
+
const.safe_constantize
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'active_model/array_serializer'
|
2
2
|
require 'active_model/serializable'
|
3
|
-
require 'active_model/serializer/
|
3
|
+
require 'active_model/serializer/association'
|
4
4
|
require 'active_model/serializer/config'
|
5
5
|
|
6
6
|
require 'thread'
|
7
|
+
require 'concurrent/map'
|
7
8
|
|
8
9
|
module ActiveModel
|
9
10
|
class Serializer
|
@@ -55,32 +56,19 @@ end
|
|
55
56
|
end
|
56
57
|
attr_reader :key_format
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
ArraySerializer
|
65
|
-
end
|
59
|
+
def serializer_for(resource, options = {})
|
60
|
+
if resource.respond_to?(:serializer_class)
|
61
|
+
resource.serializer_class
|
62
|
+
elsif resource.respond_to?(:to_ary)
|
63
|
+
if Object.constants.include?(:ArraySerializer)
|
64
|
+
::ArraySerializer
|
66
65
|
else
|
67
|
-
|
68
|
-
Object.const_get "#{resource.class.name}Serializer"
|
69
|
-
rescue NameError
|
70
|
-
nil
|
71
|
-
end
|
66
|
+
ArraySerializer
|
72
67
|
end
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
if Object.constants.include?(:ArraySerializer)
|
78
|
-
::ArraySerializer
|
79
|
-
else
|
80
|
-
ArraySerializer
|
81
|
-
end
|
82
|
-
else
|
83
|
-
"#{resource.class.name}Serializer".safe_constantize
|
68
|
+
else
|
69
|
+
klass_name = build_serializer_class(resource, options)
|
70
|
+
Serializer.serializers_cache.fetch_or_store(klass_name) do
|
71
|
+
_const_get(klass_name)
|
84
72
|
end
|
85
73
|
end
|
86
74
|
end
|
@@ -90,14 +78,19 @@ end
|
|
90
78
|
alias root= _root=
|
91
79
|
|
92
80
|
def root_name
|
93
|
-
|
81
|
+
if name
|
82
|
+
root_name = name.demodulize.underscore.sub(/_serializer$/, '')
|
83
|
+
CONFIG.plural_default_root ? root_name.pluralize : root_name
|
84
|
+
end
|
94
85
|
end
|
95
86
|
|
96
87
|
def attributes(*attrs)
|
97
|
-
@_attributes.concat attrs
|
98
|
-
|
99
88
|
attrs.each do |attr|
|
100
|
-
|
89
|
+
striped_attr = strip_attribute attr
|
90
|
+
|
91
|
+
@_attributes << striped_attr
|
92
|
+
|
93
|
+
define_method striped_attr do
|
101
94
|
object.read_attribute_for_serialization attr
|
102
95
|
end unless method_defined?(attr)
|
103
96
|
end
|
@@ -111,8 +104,28 @@ end
|
|
111
104
|
associate(Association::HasMany, *attrs)
|
112
105
|
end
|
113
106
|
|
107
|
+
def serializers_cache
|
108
|
+
@serializers_cache ||= Concurrent::Map.new
|
109
|
+
end
|
110
|
+
|
114
111
|
private
|
115
112
|
|
113
|
+
def strip_attribute(attr)
|
114
|
+
symbolized = attr.is_a?(Symbol)
|
115
|
+
|
116
|
+
attr = attr.to_s.gsub(/\?\Z/, '')
|
117
|
+
attr = attr.to_sym if symbolized
|
118
|
+
attr
|
119
|
+
end
|
120
|
+
|
121
|
+
def build_serializer_class(resource, options)
|
122
|
+
"".tap do |klass_name|
|
123
|
+
klass_name << "#{options[:namespace]}::" if options[:namespace]
|
124
|
+
klass_name << options[:prefix].to_s.classify if options[:prefix]
|
125
|
+
klass_name << "#{resource.class.name}Serializer"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
116
129
|
def associate(klass, *attrs)
|
117
130
|
options = attrs.extract_options!
|
118
131
|
|
@@ -130,6 +143,7 @@ end
|
|
130
143
|
@object = object
|
131
144
|
@scope = options[:scope]
|
132
145
|
@root = options.fetch(:root, self.class._root)
|
146
|
+
@polymorphic = options.fetch(:polymorphic, false)
|
133
147
|
@meta_key = options[:meta_key] || :meta
|
134
148
|
@meta = options[@meta_key]
|
135
149
|
@wrap_in_array = options[:_wrap_in_array]
|
@@ -137,8 +151,9 @@ end
|
|
137
151
|
@except = options[:except] ? Array(options[:except]) : nil
|
138
152
|
@key_format = options[:key_format]
|
139
153
|
@context = options[:context]
|
154
|
+
@namespace = options[:namespace]
|
140
155
|
end
|
141
|
-
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context
|
156
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta, :key_format, :context, :polymorphic
|
142
157
|
|
143
158
|
def json_key
|
144
159
|
key = if root == true || root.nil?
|
@@ -156,7 +171,7 @@ end
|
|
156
171
|
end
|
157
172
|
end
|
158
173
|
|
159
|
-
def associations
|
174
|
+
def associations(options={})
|
160
175
|
associations = self.class._associations
|
161
176
|
included_associations = filter(associations.keys)
|
162
177
|
associations.each_with_object({}) do |(name, association), hash|
|
@@ -173,7 +188,7 @@ end
|
|
173
188
|
if association.embed_namespace?
|
174
189
|
hash = hash[association.embed_namespace] ||= {}
|
175
190
|
end
|
176
|
-
hash[association.embedded_key] = serialize association
|
191
|
+
hash[association.embedded_key] = serialize association, options
|
177
192
|
end
|
178
193
|
end
|
179
194
|
end
|
@@ -194,12 +209,21 @@ end
|
|
194
209
|
included_associations = filter(associations.keys)
|
195
210
|
associations.each_with_object({}) do |(name, association), hash|
|
196
211
|
if included_associations.include? name
|
212
|
+
association_serializer = build_serializer(association)
|
213
|
+
# we must do this always because even if the current association is not
|
214
|
+
# embedded in root, it might have its own associations that are embedded in root
|
215
|
+
hash.merge!(association_serializer.embedded_in_root_associations) do |key, oldval, newval|
|
216
|
+
if oldval.respond_to?(:to_ary)
|
217
|
+
[oldval, newval].flatten.uniq
|
218
|
+
else
|
219
|
+
oldval.merge(newval) { |_, oldval, newval| [oldval, newval].flatten.uniq }
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
197
223
|
if association.embed_in_root?
|
198
224
|
if association.embed_in_root_key?
|
199
225
|
hash = hash[association.embed_in_root_key] ||= {}
|
200
226
|
end
|
201
|
-
association_serializer = build_serializer(association)
|
202
|
-
hash.merge!(association_serializer.embedded_in_root_associations) {|key, oldval, newval| [newval, oldval].flatten }
|
203
227
|
|
204
228
|
serialized_data = association_serializer.serializable_object
|
205
229
|
key = association.root_key
|
@@ -215,19 +239,29 @@ end
|
|
215
239
|
|
216
240
|
def build_serializer(association)
|
217
241
|
object = send(association.name)
|
218
|
-
association.build_serializer(object,
|
242
|
+
association.build_serializer(object, association_options_for_serializer(association))
|
243
|
+
end
|
244
|
+
|
245
|
+
def association_options_for_serializer(association)
|
246
|
+
prefix = association.options[:prefix]
|
247
|
+
namespace = association.options[:namespace] || @namespace || self.namespace
|
248
|
+
|
249
|
+
{ scope: scope }.tap do |opts|
|
250
|
+
opts[:namespace] = namespace if namespace
|
251
|
+
opts[:prefix] = prefix if prefix
|
252
|
+
end
|
219
253
|
end
|
220
254
|
|
221
|
-
def serialize(association)
|
222
|
-
build_serializer(association).serializable_object
|
255
|
+
def serialize(association,options={})
|
256
|
+
build_serializer(association).serializable_object(options)
|
223
257
|
end
|
224
258
|
|
225
259
|
def serialize_ids(association)
|
226
260
|
associated_data = send(association.name)
|
227
261
|
if associated_data.respond_to?(:to_ary)
|
228
|
-
associated_data.map { |elem| elem
|
262
|
+
associated_data.map { |elem| serialize_id(elem, association) }
|
229
263
|
else
|
230
|
-
associated_data
|
264
|
+
serialize_id(associated_data, association) if associated_data
|
231
265
|
end
|
232
266
|
end
|
233
267
|
|
@@ -255,14 +289,30 @@ end
|
|
255
289
|
end]
|
256
290
|
end
|
257
291
|
|
292
|
+
attr_writer :serialization_options
|
293
|
+
def serialization_options
|
294
|
+
@serialization_options || {}
|
295
|
+
end
|
296
|
+
|
258
297
|
def serializable_object(options={})
|
298
|
+
self.serialization_options = options
|
259
299
|
return @wrap_in_array ? [] : nil if @object.nil?
|
260
300
|
hash = attributes
|
261
|
-
hash.merge! associations
|
301
|
+
hash.merge! associations(options)
|
262
302
|
hash = convert_keys(hash) if key_format.present?
|
303
|
+
hash = { :type => type_name(@object), type_name(@object) => hash } if @polymorphic
|
263
304
|
@wrap_in_array ? [hash] : hash
|
264
305
|
end
|
265
306
|
alias_method :serializable_hash, :serializable_object
|
307
|
+
|
308
|
+
def serialize_id(elem, association)
|
309
|
+
id = elem.read_attribute_for_serialization(association.embed_key)
|
310
|
+
association.polymorphic? ? { id: id, type: type_name(elem) } : id
|
311
|
+
end
|
312
|
+
|
313
|
+
def type_name(elem)
|
314
|
+
elem.class.to_s.demodulize.underscore.to_sym
|
315
|
+
end
|
266
316
|
end
|
267
317
|
|
268
318
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'active_model/default_serializer'
|
2
|
+
require 'active_model/serializer/association/has_one'
|
3
|
+
require 'active_model/serializer/association/has_many'
|
2
4
|
|
3
5
|
module ActiveModel
|
4
6
|
class Serializer
|
@@ -13,6 +15,7 @@ module ActiveModel
|
|
13
15
|
@name = name.to_s
|
14
16
|
@options = options
|
15
17
|
self.embed = options.fetch(:embed) { CONFIG.embed }
|
18
|
+
@polymorphic = options.fetch(:polymorphic, false)
|
16
19
|
@embed_in_root = options.fetch(:embed_in_root) { options.fetch(:include) { CONFIG.embed_in_root } }
|
17
20
|
@key_format = options.fetch(:key_format) { CONFIG.key_format }
|
18
21
|
@embed_key = options[:embed_key] || :id
|
@@ -25,21 +28,22 @@ module ActiveModel
|
|
25
28
|
@serializer_from_options = serializer.is_a?(String) ? serializer.constantize : serializer
|
26
29
|
end
|
27
30
|
|
28
|
-
attr_reader :name, :embed_ids, :embed_objects
|
31
|
+
attr_reader :name, :embed_ids, :embed_objects, :polymorphic
|
29
32
|
attr_accessor :embed_in_root, :embed_key, :key, :embedded_key, :root_key, :serializer_from_options, :options, :key_format, :embed_in_root_key, :embed_namespace
|
30
33
|
alias embed_ids? embed_ids
|
31
34
|
alias embed_objects? embed_objects
|
32
35
|
alias embed_in_root? embed_in_root
|
33
36
|
alias embed_in_root_key? embed_in_root_key
|
34
37
|
alias embed_namespace? embed_namespace
|
38
|
+
alias polymorphic? polymorphic
|
35
39
|
|
36
40
|
def embed=(embed)
|
37
41
|
@embed_ids = embed == :id || embed == :ids
|
38
42
|
@embed_objects = embed == :object || embed == :objects
|
39
43
|
end
|
40
44
|
|
41
|
-
def serializer_from_object(object)
|
42
|
-
Serializer.serializer_for(object)
|
45
|
+
def serializer_from_object(object, options = {})
|
46
|
+
Serializer.serializer_for(object, options)
|
43
47
|
end
|
44
48
|
|
45
49
|
def default_serializer
|
@@ -47,55 +51,7 @@ module ActiveModel
|
|
47
51
|
end
|
48
52
|
|
49
53
|
def build_serializer(object, options = {})
|
50
|
-
serializer_class(object).new(object, options.merge(self.options))
|
51
|
-
end
|
52
|
-
|
53
|
-
class HasOne < Association
|
54
|
-
def initialize(name, *args)
|
55
|
-
super
|
56
|
-
@root_key = @embedded_key.to_s.pluralize
|
57
|
-
@key ||= "#{name}_id"
|
58
|
-
end
|
59
|
-
|
60
|
-
def serializer_class(object)
|
61
|
-
serializer_from_options || serializer_from_object(object) || default_serializer
|
62
|
-
end
|
63
|
-
|
64
|
-
def build_serializer(object, options = {})
|
65
|
-
options[:_wrap_in_array] = embed_in_root?
|
66
|
-
super
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class HasMany < Association
|
71
|
-
def initialize(name, *args)
|
72
|
-
super
|
73
|
-
@root_key = @embedded_key
|
74
|
-
@key ||= "#{name.to_s.singularize}_ids"
|
75
|
-
end
|
76
|
-
|
77
|
-
def serializer_class(object)
|
78
|
-
if use_array_serializer?
|
79
|
-
ArraySerializer
|
80
|
-
else
|
81
|
-
serializer_from_options
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def options
|
86
|
-
if use_array_serializer?
|
87
|
-
{ each_serializer: serializer_from_options }.merge! super
|
88
|
-
else
|
89
|
-
super
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def use_array_serializer?
|
96
|
-
!serializer_from_options ||
|
97
|
-
serializer_from_options && !(serializer_from_options <= ArraySerializer)
|
98
|
-
end
|
54
|
+
serializer_class(object, options).new(object, options.merge(self.options))
|
99
55
|
end
|
100
56
|
end
|
101
57
|
end
|