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.7'

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.



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/active_model/serializer.rb', line 142

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.



76
77
78
# File 'lib/active_model/serializer.rb', line 76

def _associations
  @_associations
end

._attributesObject

Returns the value of attribute _attributes.



76
77
78
# File 'lib/active_model/serializer.rb', line 76

def _attributes
  @_attributes
end

._rootObject

Returns the value of attribute _root.



76
77
78
# File 'lib/active_model/serializer.rb', line 76

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.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def context
  @context
end

#key_formatObject

Returns the value of attribute key_format.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def key_format
  @key_format
end

#metaObject

Returns the value of attribute meta.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def meta
  @meta
end

#meta_keyObject

Returns the value of attribute meta_key.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def meta_key
  @meta_key
end

#objectObject

Returns the value of attribute object.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def object
  @object
end

#polymorphicObject

Returns the value of attribute polymorphic.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def polymorphic
  @polymorphic
end

#rootObject

Returns the value of attribute root.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def root
  @root
end

#scopeObject

Returns the value of attribute scope.



156
157
158
# File 'lib/active_model/serializer.rb', line 156

def scope
  @scope
end

#serialization_optionsObject



293
294
295
# File 'lib/active_model/serializer.rb', line 293

def serialization_options
  @serialization_options || {}
end

Class Method Details

.attributes(*attrs) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/active_model/serializer.rb', line 87

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 "** Notice: embed is deprecated. **\nThe use of .embed method on a Serializer will be soon removed, as this should have a global scope and not a class scope.\nPlease use the global .setup method instead:\nActiveModel::Serializer.setup do |config|\nconfig.embed = :\#{type}\nconfig.embed_in_root = \#{CONFIG.embed_in_root || false}\nend\n"
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



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

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

.has_one(*attrs) ⇒ Object



99
100
101
# File 'lib/active_model/serializer.rb', line 99

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



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

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
# 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
    klass_name = build_serializer_class(resource, options)
    Serializer.serializers_cache.fetch_or_store(klass_name) do
      _const_get(klass_name)
    end
  end
end

.serializers_cacheObject



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

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



245
246
247
248
249
250
251
252
253
# File 'lib/active_model/serializer.rb', line 245

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



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/active_model/serializer.rb', line 174

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



168
169
170
171
172
# File 'lib/active_model/serializer.rb', line 168

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

#build_serializer(association) ⇒ Object



240
241
242
243
# File 'lib/active_model/serializer.rb', line 240

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

#convert_keys(hash) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
# File 'lib/active_model/serializer.rb', line 280

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



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/active_model/serializer.rb', line 207

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



197
198
199
200
201
202
203
204
205
# File 'lib/active_model/serializer.rb', line 197

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

#format_key(key) ⇒ Object



272
273
274
275
276
277
278
# File 'lib/active_model/serializer.rb', line 272

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

#json_keyObject



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

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



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

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



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

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

#serialize_id(elem, association) ⇒ Object



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

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



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

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



313
314
315
# File 'lib/active_model/serializer.rb', line 313

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