Class: ActiveModel::Serializer

Inherits:
Object
  • Object
show all
Includes:
Serializable
Defined in:
lib/active_model/serializer.rb,
lib/active_model/serializer/config.rb,
lib/active_model/serializer/version.rb,
lib/active_model/serializer/association.rb,
lib/active_model/serializer/association/has_one.rb,
lib/active_model/serializer/association/has_many.rb

Defined Under Namespace

Classes: Association, Config

Constant Summary collapse

EMBED_IN_ROOT_OPTIONS =
[
  :include,
  :embed_in_root,
  :embed_in_root_key,
  :embed_namespace
].freeze
CONFIG =

:nodoc:

Config.new('embed' => :objects)
VERSION =
'0.9.9'.freeze

Constants included from Serializable

ActiveModel::Serializable::INSTRUMENTATION_KEY

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Serializable

#as_json, included, #namespace, #serializable_data, #serializable_object_with_notification

Constructor Details

#initialize(object, options = {}) ⇒ Serializer

Returns a new instance of Serializer.



157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/active_model/serializer.rb', line 157

def initialize(object, options={})
  @object        = object
  @scope         = options[:scope]
  @root          = options.fetch(:root, self.class._root)
  @polymorphic   = options.fetch(:polymorphic, false)
  @meta_key      = options[:meta_key] || :meta
  @meta          = options[@meta_key]
  @wrap_in_array = options[:_wrap_in_array]
  @only          = options[:only] ? Array(options[:only]) : nil
  @except        = options[:except] ? Array(options[:except]) : nil
  @key_format    = options[:key_format]
  @context       = options[:context]
  @namespace     = options[:namespace]
end

Class Attribute Details

._associationsObject

Returns the value of attribute _associations.



80
81
82
# File 'lib/active_model/serializer.rb', line 80

def _associations
  @_associations
end

._attributesObject

Returns the value of attribute _attributes.



80
81
82
# File 'lib/active_model/serializer.rb', line 80

def _attributes
  @_attributes
end

._rootObject

Returns the value of attribute _root.



80
81
82
# File 'lib/active_model/serializer.rb', line 80

def _root
  @_root
end

.key_formatObject (readonly)

Returns the value of attribute key_format.



57
58
59
# File 'lib/active_model/serializer.rb', line 57

def key_format
  @key_format
end

Instance Attribute Details

#contextObject

Returns the value of attribute context.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def context
  @context
end

#key_formatObject

Returns the value of attribute key_format.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def key_format
  @key_format
end

#metaObject

Returns the value of attribute meta.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def meta
  @meta
end

#meta_keyObject

Returns the value of attribute meta_key.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def meta_key
  @meta_key
end

#objectObject

Returns the value of attribute object.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def object
  @object
end

#polymorphicObject

Returns the value of attribute polymorphic.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def polymorphic
  @polymorphic
end

#rootObject

Returns the value of attribute root.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def root
  @root
end

#scopeObject

Returns the value of attribute scope.



171
172
173
# File 'lib/active_model/serializer.rb', line 171

def scope
  @scope
end

#serialization_optionsObject



308
309
310
# File 'lib/active_model/serializer.rb', line 308

def serialization_options
  @serialization_options || {}
end

Class Method Details

.attributes(*attrs) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/active_model/serializer.rb', line 91

def attributes(*attrs)
  attrs.each do |attr|
    striped_attr = strip_attribute attr

    @_attributes << striped_attr

    define_method striped_attr do
      object.read_attribute_for_serialization attr
    end unless method_defined?(attr)
  end
end

.embed(type, options = {}) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/active_model/serializer.rb', line 35

def embed(type, options={})
  CONFIG.embed = type
  if EMBED_IN_ROOT_OPTIONS.any? { |opt| options[opt].present? }
    CONFIG.embed_in_root = true
  end
  if options[:embed_in_root_key].present?
    CONFIG.embed_in_root_key = options[:embed_in_root_key]
  end
  ActiveSupport::Deprecation.warn <<-WARN
** Notice: embed is deprecated. **
The use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.
Please use the global .setup method instead:
ActiveModel::Serializer.setup do |config|
  config.embed = :#{type}
  config.embed_in_root = #{CONFIG.embed_in_root || false}
end
  WARN
end

.format_keys(format) ⇒ Object



54
55
56
# File 'lib/active_model/serializer.rb', line 54

def format_keys(format)
  @key_format = format
end

.has_many(*attrs) ⇒ Object



107
108
109
# File 'lib/active_model/serializer.rb', line 107

def has_many(*attrs)
  associate(Association::HasMany, *attrs)
end

.has_one(*attrs) ⇒ Object



103
104
105
# File 'lib/active_model/serializer.rb', line 103

def has_one(*attrs)
  associate(Association::HasOne, *attrs)
end

.inherited(base) ⇒ Object



16
17
18
19
20
# File 'lib/active_model/serializer.rb', line 16

def inherited(base)
  base._root = _root
  base._attributes = (_attributes || []).dup
  base._associations = (_associations || {}).dup
end

.root_nameObject



84
85
86
87
88
89
# File 'lib/active_model/serializer.rb', line 84

def root_name
  if name
    root_name = name.demodulize.underscore.sub(/_serializer$/, '')
    CONFIG.plural_default_root ? root_name.pluralize : root_name
  end
end

.serializer_for(resource, options = {}) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/active_model/serializer.rb', line 59

def serializer_for(resource, options = {})
  if resource.respond_to?(:serializer_class)
    resource.serializer_class
  elsif resource.respond_to?(:to_ary)
    if Object.constants.include?(:ArraySerializer)
      ::ArraySerializer
    else
      ArraySerializer
    end
  else
    search_list = build_serializer_class_list(resource, options)
    result = search_list.map do |klass_name|
               Serializer.serializers_cache.fetch_or_store(klass_name) do
                 _const_get(klass_name)
               end
             end

    result.find { |serializer| !serializer.nil? }
  end
end

.serializers_cacheObject



111
112
113
# File 'lib/active_model/serializer.rb', line 111

def serializers_cache
  @serializers_cache ||= Concurrent::Map.new
end

.setupObject



22
23
24
25
26
# File 'lib/active_model/serializer.rb', line 22

def setup
  @mutex.synchronize do
    yield CONFIG
  end
end

Instance Method Details

#association_options_for_serializer(association) ⇒ Object



260
261
262
263
264
265
266
267
268
# File 'lib/active_model/serializer.rb', line 260

def association_options_for_serializer(association)
  prefix    = association.options[:prefix]
  namespace = association.options[:namespace] || @namespace || self.namespace

  { scope: scope }.tap do |opts|
    opts[:namespace] = namespace if namespace
    opts[:prefix]    = prefix    if prefix
  end
end

#associations(options = {}) ⇒ Object



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/active_model/serializer.rb', line 189

def associations(options={})
  associations = self.class._associations
  included_associations = filter(associations.keys)
  associations.each_with_object({}) do |(name, association), hash|
    if included_associations.include? name
      if association.embed_ids?
        ids = serialize_ids association
        if association.embed_namespace?
          hash = hash[association.embed_namespace] ||= {}
          hash[association.key] = ids
        else
          hash[association.key] = ids
        end
      elsif association.embed_objects?
        if association.embed_namespace?
          hash = hash[association.embed_namespace] ||= {}
        end
        hash[association.embedded_key] = serialize association, options
      end
    end
  end
end

#attributesObject



183
184
185
186
187
# File 'lib/active_model/serializer.rb', line 183

def attributes
  filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
    hash[name] = send(name)
  end
end

#build_serializer(association) ⇒ Object



255
256
257
258
# File 'lib/active_model/serializer.rb', line 255

def build_serializer(association)
  object = send(association.name)
  association.build_serializer(object, association_options_for_serializer(association))
end

#convert_keys(hash) ⇒ Object



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/active_model/serializer.rb', line 295

def convert_keys(hash)
  Hash[hash.map do |k,v|
    key = if k.is_a?(Symbol)
      format_key(k).to_sym
    else
      format_key(k)
    end

    [key ,v]
  end]
end

#embedded_in_root_associationsObject



222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/active_model/serializer.rb', line 222

def embedded_in_root_associations
  associations = self.class._associations
  included_associations = filter(associations.keys)
  associations.each_with_object({}) do |(name, association), hash|
    if included_associations.include? name
      association_serializer = build_serializer(association)
      # we must do this always because even if the current association is not
      # embedded in root, it might have its own associations that are embedded in root
      hash.merge!(association_serializer.embedded_in_root_associations) do |key, oldval, newval|
        if oldval.respond_to?(:to_ary)
          [oldval, newval].flatten.uniq
        else
          oldval.merge(newval) { |_, oldval, newval| [oldval, newval].flatten.uniq }
        end
      end

      if association.embed_in_root?
        if association.embed_in_root_key?
          hash = hash[association.embed_in_root_key] ||= {}
        end

        serialized_data = association_serializer.serializable_object
        key = association.root_key
        if hash.has_key?(key)
          hash[key].concat(serialized_data).uniq!
        else
          hash[key] = serialized_data
        end
      end
    end
  end
end

#filter(keys) ⇒ Object



212
213
214
215
216
217
218
219
220
# File 'lib/active_model/serializer.rb', line 212

def filter(keys)
  if @only
    keys & @only
  elsif @except
    keys - @except
  else
    keys
  end
end

#format_key(key) ⇒ Object



287
288
289
290
291
292
293
# File 'lib/active_model/serializer.rb', line 287

def format_key(key)
  if key_format == :lower_camel
    key.to_s.camelize(:lower)
  else
    key
  end
end

#json_keyObject



173
174
175
176
177
178
179
180
181
# File 'lib/active_model/serializer.rb', line 173

def json_key
  key = if root == true || root.nil?
    self.class.root_name
  else
    root
  end

  key_format == :lower_camel && key.present? ? key.camelize(:lower) : key
end

#serializable_object(options = {}) ⇒ Object Also known as: serializable_hash



312
313
314
315
316
317
318
319
320
# File 'lib/active_model/serializer.rb', line 312

def serializable_object(options={})
  self.serialization_options = options
  return @wrap_in_array ? [] : nil if @object.nil?
  hash = attributes
  hash.merge! associations(options)
  hash = convert_keys(hash) if key_format.present?
  hash = { :type => type_name(@object), type_name(@object) => hash } if @polymorphic
  @wrap_in_array ? [hash] : hash
end

#serialize(association, options = {}) ⇒ Object



270
271
272
# File 'lib/active_model/serializer.rb', line 270

def serialize(association,options={})
  build_serializer(association).serializable_object(options)
end

#serialize_id(elem, association) ⇒ Object



323
324
325
326
# File 'lib/active_model/serializer.rb', line 323

def serialize_id(elem, association)
  id = elem.read_attribute_for_serialization(association.embed_key)
  association.polymorphic? ? { id: id, type: type_name(elem) } : id
end

#serialize_ids(association) ⇒ Object



274
275
276
277
278
279
280
281
# File 'lib/active_model/serializer.rb', line 274

def serialize_ids(association)
  associated_data = send(association.name)
  if associated_data.respond_to?(:to_ary)
    associated_data.map { |elem| serialize_id(elem, association) }
  else
    serialize_id(associated_data, association) if associated_data
  end
end

#type_name(elem) ⇒ Object



328
329
330
# File 'lib/active_model/serializer.rb', line 328

def type_name(elem)
  elem.class.to_s.demodulize.underscore.to_sym
end