active_model_serializers 0.8.3 → 0.9.0.alpha1
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 +4 -4
- data/CHANGELOG.md +25 -5
- data/CONTRIBUTING.md +20 -0
- data/DESIGN.textile +4 -4
- data/{MIT-LICENSE.txt → MIT-LICENSE} +0 -0
- data/README.md +187 -96
- data/lib/action_controller/serialization.rb +30 -16
- data/lib/active_model/array_serializer.rb +36 -82
- data/lib/active_model/default_serializer.rb +22 -0
- data/lib/active_model/serializable.rb +25 -0
- data/lib/active_model/serializer/associations.rb +53 -211
- data/lib/active_model/serializer/config.rb +31 -0
- data/lib/active_model/serializer/generators/resource_override.rb +13 -0
- data/lib/{generators → active_model/serializer/generators}/serializer/USAGE +0 -0
- data/lib/active_model/serializer/generators/serializer/scaffold_controller_generator.rb +14 -0
- data/lib/active_model/serializer/generators/serializer/serializer_generator.rb +37 -0
- data/lib/active_model/serializer/generators/serializer/templates/controller.rb +93 -0
- data/lib/active_model/serializer/generators/serializer/templates/serializer.rb +8 -0
- data/lib/active_model/serializer/railtie.rb +10 -0
- data/lib/active_model/{serializers → serializer}/version.rb +1 -1
- data/lib/active_model/serializer.rb +126 -448
- data/lib/active_model/serializer_support.rb +5 -0
- data/lib/active_model_serializers.rb +7 -86
- data/test/coverage_setup.rb +15 -0
- data/test/fixtures/active_record.rb +92 -0
- data/test/fixtures/poro.rb +64 -0
- data/test/integration/action_controller/serialization_test.rb +234 -0
- data/test/integration/active_record/active_record_test.rb +77 -0
- data/test/integration/generators/resource_generator_test.rb +26 -0
- data/test/integration/generators/scaffold_controller_generator_test.rb +67 -0
- data/test/integration/generators/serializer_generator_test.rb +41 -0
- data/test/test_app.rb +11 -0
- data/test/test_helper.rb +8 -19
- data/test/tmp/app/serializers/account_serializer.rb +3 -0
- data/test/unit/active_model/array_serializer/meta_test.rb +53 -0
- data/test/unit/active_model/array_serializer/root_test.rb +102 -0
- data/test/unit/active_model/array_serializer/scope_test.rb +24 -0
- data/test/unit/active_model/array_serializer/serialization_test.rb +83 -0
- data/test/unit/active_model/default_serializer_test.rb +13 -0
- data/test/unit/active_model/serializer/associations/build_serializer_test.rb +21 -0
- data/test/unit/active_model/serializer/associations_test.rb +19 -0
- data/test/unit/active_model/serializer/attributes_test.rb +41 -0
- data/test/unit/active_model/serializer/config_test.rb +86 -0
- data/test/unit/active_model/serializer/filter_test.rb +49 -0
- data/test/unit/active_model/serializer/has_many_test.rb +173 -0
- data/test/unit/active_model/serializer/has_one_test.rb +151 -0
- data/test/unit/active_model/serializer/meta_test.rb +39 -0
- data/test/unit/active_model/serializer/root_test.rb +117 -0
- data/test/unit/active_model/serializer/scope_test.rb +49 -0
- metadata +80 -65
- data/.gitignore +0 -18
- data/.travis.yml +0 -28
- data/Gemfile +0 -4
- data/Gemfile.edge +0 -9
- data/Rakefile +0 -18
- data/active_model_serializers.gemspec +0 -24
- data/bench/perf.rb +0 -43
- data/cruft.md +0 -19
- data/lib/active_record/serializer_override.rb +0 -16
- data/lib/generators/resource_override.rb +0 -13
- data/lib/generators/serializer/serializer_generator.rb +0 -42
- data/lib/generators/serializer/templates/serializer.rb +0 -19
- data/test/array_serializer_test.rb +0 -75
- data/test/association_test.rb +0 -592
- data/test/caching_test.rb +0 -96
- data/test/generators_test.rb +0 -85
- data/test/no_serialization_scope_test.rb +0 -34
- data/test/serialization_scope_name_test.rb +0 -67
- data/test/serialization_test.rb +0 -392
- data/test/serializer_support_test.rb +0 -51
- data/test/serializer_test.rb +0 -1465
- data/test/test_fakes.rb +0 -217
@@ -1,515 +1,193 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require '
|
4
|
-
require '
|
1
|
+
require 'active_model/array_serializer'
|
2
|
+
require 'active_model/serializable'
|
3
|
+
require 'active_model/serializer/associations'
|
4
|
+
require 'active_model/serializer/config'
|
5
|
+
|
6
|
+
require 'thread'
|
5
7
|
|
6
8
|
module ActiveModel
|
7
|
-
# Active Model Serializer
|
8
|
-
#
|
9
|
-
# Provides a basic serializer implementation that allows you to easily
|
10
|
-
# control how a given object is going to be serialized. On initialization,
|
11
|
-
# it expects two objects as arguments, a resource and options. For example,
|
12
|
-
# one may do in a controller:
|
13
|
-
#
|
14
|
-
# PostSerializer.new(@post, :scope => current_user).to_json
|
15
|
-
#
|
16
|
-
# The object to be serialized is the +@post+ and the current user is passed
|
17
|
-
# in for authorization purposes.
|
18
|
-
#
|
19
|
-
# We use the scope to check if a given attribute should be serialized or not.
|
20
|
-
# For example, some attributes may only be returned if +current_user+ is the
|
21
|
-
# author of the post:
|
22
|
-
#
|
23
|
-
# class PostSerializer < ActiveModel::Serializer
|
24
|
-
# attributes :title, :body
|
25
|
-
# has_many :comments
|
26
|
-
#
|
27
|
-
# private
|
28
|
-
#
|
29
|
-
# def attributes
|
30
|
-
# hash = super
|
31
|
-
# hash.merge!(:email => post.email) if author?
|
32
|
-
# hash
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
# def author?
|
36
|
-
# post.author == scope
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
9
|
class Serializer
|
41
|
-
|
42
|
-
|
43
|
-
INCLUDE_METHODS = {}
|
44
|
-
INSTRUMENT = { :serialize => :"serialize.serializer", :associations => :"associations.serializer" }
|
45
|
-
|
46
|
-
class IncludeError < StandardError
|
47
|
-
attr_reader :source, :association
|
48
|
-
|
49
|
-
def initialize(source, association)
|
50
|
-
@source, @association = source, association
|
51
|
-
end
|
52
|
-
|
53
|
-
def to_s
|
54
|
-
"Cannot serialize #{association} when #{source} does not have a root!"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class_attribute :_attributes
|
59
|
-
self._attributes = {}
|
10
|
+
include Serializable
|
60
11
|
|
61
|
-
|
62
|
-
self._associations = {}
|
63
|
-
|
64
|
-
class_attribute :_root
|
65
|
-
class_attribute :_embed
|
66
|
-
self._embed = :objects
|
67
|
-
class_attribute :_root_embed
|
68
|
-
|
69
|
-
class_attribute :cache
|
70
|
-
class_attribute :perform_caching
|
12
|
+
@mutex = Mutex.new
|
71
13
|
|
72
14
|
class << self
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
# Define attributes to be used in the serialization.
|
79
|
-
def attributes(*attrs)
|
80
|
-
|
81
|
-
self._attributes = _attributes.dup
|
82
|
-
|
83
|
-
attrs.each do |attr|
|
84
|
-
if Hash === attr
|
85
|
-
attr.each {|attr_real, key| attribute attr_real, :key => key }
|
86
|
-
else
|
87
|
-
attribute attr
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def attribute(attr, options={})
|
93
|
-
self._attributes = _attributes.merge(attr.is_a?(Hash) ? attr : {attr => options[:key] || attr.to_s.gsub(/\?$/, '').to_sym})
|
94
|
-
|
95
|
-
attr = attr.keys[0] if attr.is_a? Hash
|
96
|
-
|
97
|
-
unless method_defined?(attr)
|
98
|
-
define_method attr do
|
99
|
-
object.read_attribute_for_serialization(attr.to_sym)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
define_include_method attr
|
104
|
-
|
105
|
-
# protect inheritance chains and open classes
|
106
|
-
# if a serializer inherits from another OR
|
107
|
-
# attributes are added later in a classes lifecycle
|
108
|
-
# poison the cache
|
109
|
-
define_method :_fast_attributes do
|
110
|
-
raise NameError
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
def associate(klass, attrs) #:nodoc:
|
116
|
-
options = attrs.extract_options!
|
117
|
-
self._associations = _associations.dup
|
118
|
-
|
119
|
-
attrs.each do |attr|
|
120
|
-
unless method_defined?(attr)
|
121
|
-
define_method attr do
|
122
|
-
object.send attr
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
define_include_method attr
|
127
|
-
|
128
|
-
self._associations[attr] = klass.refine(attr, options)
|
129
|
-
end
|
15
|
+
def inherited(base)
|
16
|
+
base._root = _root
|
17
|
+
base._attributes = (_attributes || []).dup
|
18
|
+
base._associations = (_associations || {}).dup
|
130
19
|
end
|
131
20
|
|
132
|
-
def
|
133
|
-
|
134
|
-
|
135
|
-
INCLUDE_METHODS[name] = method
|
136
|
-
|
137
|
-
unless method_defined?(method)
|
138
|
-
define_method method do
|
139
|
-
true
|
140
|
-
end
|
21
|
+
def setup
|
22
|
+
@mutex.synchronize do
|
23
|
+
yield CONFIG
|
141
24
|
end
|
142
25
|
end
|
143
26
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
# The serializer object should implement the association name
|
157
|
-
# as a method which should return an object when invoked. If a method
|
158
|
-
# with the association name does not exist, the association name is
|
159
|
-
# dispatched to the serialized object.
|
160
|
-
def has_one(*attrs)
|
161
|
-
associate(Associations::HasOne, attrs)
|
27
|
+
def embed(type, options={})
|
28
|
+
CONFIG.embed = type
|
29
|
+
CONFIG.embed_in_root = true if options[:embed_in_root] || options[:include]
|
30
|
+
ActiveSupport::Deprecation.warn <<-WARN
|
31
|
+
** Notice: embed is deprecated. **
|
32
|
+
The use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.
|
33
|
+
Please use the global .setup method instead:
|
34
|
+
ActiveModel::Serializer.setup do |config|
|
35
|
+
config.embed = :#{type}
|
36
|
+
config.embed_in_root = #{CONFIG.embed_in_root || false}
|
37
|
+
end
|
38
|
+
WARN
|
162
39
|
end
|
163
40
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
#
|
169
|
-
# The +attributes+ hash looks like this:
|
170
|
-
#
|
171
|
-
# { :name => :string, :age => :integer }
|
172
|
-
#
|
173
|
-
# The +associations+ hash looks like this:
|
174
|
-
# { :posts => { :has_many => :posts } }
|
175
|
-
#
|
176
|
-
# If :key is used:
|
177
|
-
#
|
178
|
-
# class PostsSerializer < ActiveModel::Serializer
|
179
|
-
# has_many :posts, :key => :my_posts
|
180
|
-
# end
|
181
|
-
#
|
182
|
-
# the hash looks like this:
|
183
|
-
#
|
184
|
-
# { :my_posts => { :has_many => :posts }
|
185
|
-
#
|
186
|
-
# This information is extracted from the serializer's model class,
|
187
|
-
# which is provided by +SerializerClass.model_class+.
|
188
|
-
#
|
189
|
-
# The schema method uses the +columns_hash+ and +reflect_on_association+
|
190
|
-
# methods, provided by default by ActiveRecord. You can implement these
|
191
|
-
# methods on your custom models if you want the serializer's schema method
|
192
|
-
# to work.
|
193
|
-
#
|
194
|
-
# TODO: This is currently coupled to Active Record. We need to
|
195
|
-
# figure out a way to decouple those two.
|
196
|
-
def schema
|
197
|
-
klass = model_class
|
198
|
-
columns = klass.columns_hash
|
199
|
-
|
200
|
-
attrs = {}
|
201
|
-
_attributes.each do |name, key|
|
202
|
-
if column = columns[name.to_s]
|
203
|
-
attrs[key] = column.type
|
41
|
+
if RUBY_VERSION >= '2.0'
|
42
|
+
def serializer_for(resource)
|
43
|
+
if resource.respond_to?(:to_ary)
|
44
|
+
ArraySerializer
|
204
45
|
else
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
else
|
210
|
-
attrs[key] = nil
|
46
|
+
begin
|
47
|
+
Object.const_get "#{resource.class.name}Serializer"
|
48
|
+
rescue NameError
|
49
|
+
nil
|
211
50
|
end
|
212
51
|
end
|
213
52
|
end
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
if model_association = klass.reflect_on_association(association.name)
|
220
|
-
# Real association.
|
221
|
-
associations[association.key] = { model_association.macro => model_association.name }
|
53
|
+
else
|
54
|
+
def serializer_for(resource)
|
55
|
+
if resource.respond_to?(:to_ary)
|
56
|
+
ArraySerializer
|
222
57
|
else
|
223
|
-
#
|
224
|
-
# the association class, but that would make it different from
|
225
|
-
# real associations, which read has_one vs. belongs_to from the
|
226
|
-
# model.
|
227
|
-
associations[association.key] = nil
|
58
|
+
"#{resource.class.name}Serializer".safe_constantize
|
228
59
|
end
|
229
60
|
end
|
230
|
-
|
231
|
-
{ :attributes => attrs, :associations => associations }
|
232
|
-
end
|
233
|
-
|
234
|
-
# The model class associated with this serializer.
|
235
|
-
def model_class
|
236
|
-
name.sub(/Serializer$/, '').constantize
|
237
61
|
end
|
238
62
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
# embed :ids # Embed only the association ids
|
243
|
-
# embed :ids, :include => true # Embed the association ids and include objects in the root
|
244
|
-
#
|
245
|
-
def embed(type, options={})
|
246
|
-
self._embed = type
|
247
|
-
self._root_embed = true if options[:include]
|
248
|
-
end
|
63
|
+
attr_accessor :_root, :_attributes, :_associations
|
64
|
+
alias root _root=
|
65
|
+
alias root= _root=
|
249
66
|
|
250
|
-
|
251
|
-
|
252
|
-
self._root = name
|
67
|
+
def root_name
|
68
|
+
name.demodulize.underscore.sub(/_serializer$/, '') if name
|
253
69
|
end
|
254
|
-
alias_method :root=, :root
|
255
|
-
|
256
|
-
# Used internally to create a new serializer object based on controller
|
257
|
-
# settings and options for a given resource. These settings are typically
|
258
|
-
# set during the request lifecycle or by the controller class, and should
|
259
|
-
# not be manually defined for this method.
|
260
|
-
def build_json(controller, resource, options)
|
261
|
-
default_options = controller.send(:default_serializer_options) || {}
|
262
|
-
options = default_options.merge(options || {})
|
263
|
-
|
264
|
-
serializer = options.delete(:serializer) ||
|
265
|
-
(resource.respond_to?(:active_model_serializer) &&
|
266
|
-
resource.active_model_serializer)
|
267
70
|
|
268
|
-
|
269
|
-
|
270
|
-
if resource.respond_to?(:to_ary)
|
271
|
-
unless serializer <= ActiveModel::ArraySerializer
|
272
|
-
raise ArgumentError.new("#{serializer.name} is not an ArraySerializer. " +
|
273
|
-
"You may want to use the :each_serializer option instead.")
|
274
|
-
end
|
71
|
+
def attributes(*attrs)
|
72
|
+
@_attributes.concat attrs
|
275
73
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
end
|
74
|
+
attrs.each do |attr|
|
75
|
+
define_method attr do
|
76
|
+
object.read_attribute_for_serialization attr
|
77
|
+
end unless method_defined?(attr)
|
280
78
|
end
|
281
|
-
|
282
|
-
options[:scope] = controller.serialization_scope unless options.has_key?(:scope)
|
283
|
-
options[:scope_name] = controller._serialization_scope
|
284
|
-
options[:url_options] = controller.url_options
|
285
|
-
|
286
|
-
serializer.new(resource, options)
|
287
79
|
end
|
288
|
-
end
|
289
80
|
|
290
|
-
|
291
|
-
|
292
|
-
def initialize(object, options={})
|
293
|
-
@object, @options = object, options
|
294
|
-
|
295
|
-
scope_name = @options[:scope_name]
|
296
|
-
if scope_name && !respond_to?(scope_name)
|
297
|
-
self.class.class_eval do
|
298
|
-
define_method scope_name, lambda { scope }
|
299
|
-
end
|
81
|
+
def has_one(*attrs)
|
82
|
+
associate(Association::HasOne, *attrs)
|
300
83
|
end
|
301
|
-
end
|
302
|
-
|
303
|
-
def root_name
|
304
|
-
return false if self._root == false
|
305
|
-
|
306
|
-
class_name = self.class.name.demodulize.underscore.sub(/_serializer$/, '').to_sym unless self.class.name.blank?
|
307
84
|
|
308
|
-
|
309
|
-
|
310
|
-
else
|
311
|
-
self._root || class_name
|
85
|
+
def has_many(*attrs)
|
86
|
+
associate(Association::HasMany, *attrs)
|
312
87
|
end
|
313
|
-
end
|
314
88
|
|
315
|
-
|
316
|
-
@options[:url_options] || {}
|
317
|
-
end
|
89
|
+
private
|
318
90
|
|
319
|
-
|
320
|
-
|
321
|
-
end
|
91
|
+
def associate(klass, *attrs)
|
92
|
+
options = attrs.extract_options!
|
322
93
|
|
323
|
-
|
324
|
-
|
325
|
-
|
94
|
+
attrs.each do |attr|
|
95
|
+
define_method attr do
|
96
|
+
object.send attr
|
97
|
+
end unless method_defined?(attr)
|
326
98
|
|
327
|
-
|
328
|
-
if perform_caching?
|
329
|
-
cache.fetch expand_cache_key([self.class.to_s.underscore, cache_key, 'to-json']) do
|
330
|
-
super
|
99
|
+
@_associations[attr] = klass.new(attr, options)
|
331
100
|
end
|
332
|
-
else
|
333
|
-
super
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
# Returns a json representation of the serializable
|
338
|
-
# object including the root.
|
339
|
-
def as_json(options={})
|
340
|
-
options ||= {}
|
341
|
-
if root = options.fetch(:root, @options.fetch(:root, root_name))
|
342
|
-
@options[:hash] = hash = {}
|
343
|
-
@options[:unique_values] = {}
|
344
|
-
|
345
|
-
hash.merge!(root => serializable_hash)
|
346
|
-
include_meta hash
|
347
|
-
hash
|
348
|
-
else
|
349
|
-
serializable_hash
|
350
101
|
end
|
351
102
|
end
|
352
103
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
104
|
+
def initialize(object, options={})
|
105
|
+
@object = object
|
106
|
+
@scope = options[:scope]
|
107
|
+
@root = options.fetch(:root, self.class._root)
|
108
|
+
@meta_key = options[:meta_key] || :meta
|
109
|
+
@meta = options[@meta_key]
|
110
|
+
@wrap_in_array = options[:_wrap_in_array]
|
111
|
+
end
|
112
|
+
attr_accessor :object, :scope, :root, :meta_key, :meta
|
113
|
+
|
114
|
+
def json_key
|
115
|
+
if root == true || root.nil?
|
116
|
+
self.class.root_name
|
360
117
|
else
|
361
|
-
|
118
|
+
root
|
362
119
|
end
|
363
120
|
end
|
364
121
|
|
365
|
-
def
|
366
|
-
|
367
|
-
|
122
|
+
def attributes
|
123
|
+
filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
|
124
|
+
hash[name] = send(name)
|
368
125
|
end
|
369
126
|
end
|
370
127
|
|
371
|
-
def
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
# passed in is the same as the current options hash, use the current
|
381
|
-
# unique values.
|
382
|
-
#
|
383
|
-
# TODO: Should passing in a Hash even be public API here?
|
384
|
-
unique_values =
|
385
|
-
if hash = options[:hash]
|
386
|
-
if @options[:hash] == hash
|
387
|
-
@options[:unique_values] ||= {}
|
388
|
-
else
|
389
|
-
{}
|
128
|
+
def associations
|
129
|
+
associations = self.class._associations
|
130
|
+
included_associations = filter(associations.keys)
|
131
|
+
associations.each_with_object({}) do |(name, association), hash|
|
132
|
+
if included_associations.include? name
|
133
|
+
if association.embed_ids?
|
134
|
+
hash[association.key] = serialize_ids association
|
135
|
+
elsif association.embed_objects?
|
136
|
+
hash[association.embedded_key] = serialize association
|
390
137
|
end
|
391
|
-
else
|
392
|
-
hash = @options[:hash]
|
393
|
-
@options[:unique_values] ||= {}
|
394
|
-
end
|
395
|
-
|
396
|
-
node = options[:node] ||= @node
|
397
|
-
value = options[:value]
|
398
|
-
|
399
|
-
if options[:include] == nil
|
400
|
-
if @options.key?(:include)
|
401
|
-
options[:include] = @options[:include].include?(name)
|
402
|
-
elsif @options.include?(:exclude)
|
403
|
-
options[:include] = !@options[:exclude].include?(name)
|
404
138
|
end
|
405
139
|
end
|
406
|
-
|
407
|
-
association_class =
|
408
|
-
if klass = _associations[name]
|
409
|
-
klass
|
410
|
-
elsif value.respond_to?(:to_ary)
|
411
|
-
Associations::HasMany
|
412
|
-
else
|
413
|
-
Associations::HasOne
|
414
|
-
end
|
415
|
-
|
416
|
-
association = association_class.new(name, self, options)
|
417
|
-
|
418
|
-
if association.embed_ids?
|
419
|
-
node[association.key] = association.serialize_ids
|
420
|
-
|
421
|
-
if association.embed_in_root? && hash.nil?
|
422
|
-
raise IncludeError.new(self.class, association.name)
|
423
|
-
elsif association.embed_in_root? && association.embeddable?
|
424
|
-
merge_association hash, association.root, association.serializables, unique_values
|
425
|
-
end
|
426
|
-
elsif association.embed_objects?
|
427
|
-
node[association.key] = association.serialize
|
428
|
-
end
|
429
140
|
end
|
430
141
|
|
431
|
-
|
432
|
-
|
433
|
-
# which has_many tags, the top-level :tags key will contain the merged list
|
434
|
-
# of all tags for all comments of the post.
|
435
|
-
#
|
436
|
-
# In order to make this efficient, we store a :unique_values hash containing
|
437
|
-
# a unique list of all of the objects that are already in the Array. This
|
438
|
-
# avoids the need to scan through the Array looking for entries every time
|
439
|
-
# we want to merge a new list of values.
|
440
|
-
def merge_association(hash, key, serializables, unique_values)
|
441
|
-
already_serialized = (unique_values[key] ||= {})
|
442
|
-
serializable_hashes = (hash[key] ||= [])
|
443
|
-
|
444
|
-
serializables.each do |serializable|
|
445
|
-
unless already_serialized.include? serializable.object
|
446
|
-
already_serialized[serializable.object] = true
|
447
|
-
serializable_hashes << serializable.serializable_hash
|
448
|
-
end
|
449
|
-
end
|
142
|
+
def filter(keys)
|
143
|
+
keys
|
450
144
|
end
|
451
145
|
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
146
|
+
def embedded_in_root_associations
|
147
|
+
associations = self.class._associations
|
148
|
+
included_associations = filter(associations.keys)
|
149
|
+
associations.each_with_object({}) do |(name, association), hash|
|
150
|
+
if included_associations.include? name
|
151
|
+
if association.embed_in_root?
|
152
|
+
association_serializer = build_serializer(association)
|
153
|
+
hash.merge! association_serializer.embedded_in_root_associations
|
460
154
|
|
461
|
-
|
462
|
-
|
155
|
+
serialized_data = association_serializer.serializable_object
|
156
|
+
key = association.root_key
|
157
|
+
if hash.has_key?(key)
|
158
|
+
hash[key].concat(serialized_data).uniq!
|
159
|
+
else
|
160
|
+
hash[key] = serialized_data
|
161
|
+
end
|
162
|
+
end
|
463
163
|
end
|
464
|
-
|
465
|
-
|
466
|
-
self.class.class_eval method
|
467
|
-
_fast_attributes
|
468
|
-
end
|
469
|
-
|
470
|
-
# Returns options[:scope]
|
471
|
-
def scope
|
472
|
-
@options[:scope]
|
473
|
-
end
|
474
|
-
|
475
|
-
alias :read_attribute_for_serialization :send
|
476
|
-
|
477
|
-
def _serializable_hash
|
478
|
-
return nil if @object.nil?
|
479
|
-
@node = attributes
|
480
|
-
include_associations! if _embed
|
481
|
-
@node
|
482
|
-
end
|
483
|
-
|
484
|
-
def perform_caching?
|
485
|
-
perform_caching && cache && respond_to?(:cache_key)
|
164
|
+
end
|
486
165
|
end
|
487
166
|
|
488
|
-
def
|
489
|
-
|
167
|
+
def build_serializer(association)
|
168
|
+
object = send(association.name)
|
169
|
+
association.build_serializer(object, scope: scope)
|
490
170
|
end
|
491
171
|
|
492
|
-
|
493
|
-
|
494
|
-
def instrument(name, payload = {}, &block)
|
495
|
-
event_name = INSTRUMENT[name]
|
496
|
-
ActiveSupport::Notifications.instrument(event_name, payload, &block)
|
172
|
+
def serialize(association)
|
173
|
+
build_serializer(association).serializable_object
|
497
174
|
end
|
498
|
-
end
|
499
175
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
def initialize(object, options={})
|
508
|
-
@object, @options = object, options
|
176
|
+
def serialize_ids(association)
|
177
|
+
associated_data = send(association.name)
|
178
|
+
if associated_data.respond_to?(:to_ary)
|
179
|
+
associated_data.map { |elem| elem.read_attribute_for_serialization(association.embed_key) }
|
180
|
+
else
|
181
|
+
associated_data.read_attribute_for_serialization(association.embed_key) if associated_data
|
182
|
+
end
|
509
183
|
end
|
510
184
|
|
511
|
-
def
|
512
|
-
|
185
|
+
def serializable_object(options={})
|
186
|
+
return nil if object.nil?
|
187
|
+
hash = attributes
|
188
|
+
hash.merge! associations
|
189
|
+
@wrap_in_array ? [hash] : hash
|
513
190
|
end
|
191
|
+
alias_method :serializable_hash, :serializable_object
|
514
192
|
end
|
515
193
|
end
|