active_model_serializers 0.9.0 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|