Class: ActiveModel::Serializer

Inherits:
Object
  • Object
show all
Extended by:
ActiveModelSerializers::Deprecate, ActiveSupport::Autoload
Includes:
Caching, ActiveSupport::Configurable
Defined in:
lib/active_model/serializer.rb,
lib/active_model/serializer/lint.rb,
lib/active_model/serializer/null.rb,
lib/active_model/serializer/field.rb,
lib/active_model/serializer/adapter.rb,
lib/active_model/serializer/version.rb,
lib/active_model/serializer/fieldset.rb,
lib/active_model/serializer/attribute.rb,
lib/active_model/serializer/reflection.rb,
lib/active_model/serializer/association.rb,
lib/active_model/serializer/adapter/base.rb,
lib/active_model/serializer/adapter/json.rb,
lib/active_model/serializer/adapter/null.rb,
lib/active_model/serializer/adapter/json_api.rb,
lib/active_model/serializer/array_serializer.rb,
lib/active_model/serializer/concerns/caching.rb,
lib/active_model/serializer/error_serializer.rb,
lib/active_model/serializer/lazy_association.rb,
lib/active_model/serializer/errors_serializer.rb,
lib/active_model/serializer/adapter/attributes.rb,
lib/active_model/serializer/has_one_reflection.rb,
lib/active_model/serializer/has_many_reflection.rb,
lib/active_model/serializer/belongs_to_reflection.rb,
lib/active_model/serializer/collection_serializer.rb

Direct Known Subclasses

ErrorSerializer, Null

Defined Under Namespace

Modules: Adapter, Caching, Lint Classes: ArraySerializer, Association, Attribute, BelongsToReflection, CollectionSerializer, ErrorSerializer, ErrorsSerializer, Field, Fieldset, HasManyReflection, HasOneReflection, LazyAssociation, Null, Reflection

Constant Summary collapse

SERIALIZABLE_HASH_VALID_KEYS =
[:only, :except, :methods, :include, :root].freeze
VERSION =
'0.10.6'.freeze
UndefinedCacheKey =
Class.new(StandardError)

Constants included from Caching

Caching::CALLER_FILE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveModelSerializers::Deprecate

delegate_and_deprecate, deprecate

Methods included from Caching

#cache_key, #expand_cache_key, #fetch, #fetch_attributes, #fetch_attributes_fragment, #object_cache_key, #serializer_class

Constructor Details

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

`scope_name` is set as :current_user by default in the controller. If the instance does not have a method named `scope_name`, it defines the method so that it calls the scope.


309
310
311
312
313
314
315
316
317
318
# File 'lib/active_model/serializer.rb', line 309

def initialize(object, options = {})
  self.object = object
  self.instance_options = options
  self.root = instance_options[:root]
  self.scope = instance_options[:scope]

  return if !(scope_name = instance_options[:scope_name]) || respond_to?(scope_name)

  define_singleton_method scope_name, -> { scope }
end

Instance Attribute Details

#objectObject

END SERIALIZER MACROS


304
305
306
# File 'lib/active_model/serializer.rb', line 304

def object
  @object
end

#rootObject

END SERIALIZER MACROS


304
305
306
# File 'lib/active_model/serializer.rb', line 304

def root
  @root
end

#scopeObject

END SERIALIZER MACROS


304
305
306
# File 'lib/active_model/serializer.rb', line 304

def scope
  @scope
end

Class Method Details

._attributesArray<Symbol>

Returns Key names of declared attributes.

Returns:

  • (Array<Symbol>)

    Key names of declared attributes

See Also:

  • Serializer::attribute

192
193
194
# File 'lib/active_model/serializer.rb', line 192

def self._attributes
  _attributes_data.keys
end

.adapterObject

Deprecated


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

def self.adapter
  ActiveModelSerializers::Adapter.lookup(config.adapter)
end

.attribute(attr, options = {}, &block) ⇒ Object

Examples:

class AdminAuthorSerializer < ActiveModel::Serializer
  attributes :id, :recent_edits
  attribute :name, key: :title

  attribute :full_name do
    "#{object.first_name} #{object.last_name}"
  end

  def recent_edits
    object.edits.last(5)
  end

221
222
223
224
# File 'lib/active_model/serializer.rb', line 221

def self.attribute(attr, options = {}, &block)
  key = options.fetch(:key, attr)
  _attributes_data[key] = Attribute.new(attr, options, block)
end

.attributes(*attrs) ⇒ Object

Examples:

class AdminAuthorSerializer < ActiveModel::Serializer
  attributes :id, :name, :recent_edits

201
202
203
204
205
206
207
# File 'lib/active_model/serializer.rb', line 201

def self.attributes(*attrs)
  attrs = attrs.first if attrs.first.class == Array

  attrs.each do |attr|
    attribute(attr)
  end
end

.belongs_to(name, options = {}, &block) ⇒ void

This method returns an undefined value.

Examples:

belongs_to :author, serializer: AuthorSerializer

Parameters:

  • name (Symbol)

    of the association

  • options (Hash<Symbol => any>) (defaults to: {})

    for the reflection


244
245
246
# File 'lib/active_model/serializer.rb', line 244

def self.belongs_to(name, options = {}, &block)
  associate(BelongsToReflection.new(name, options, block))
end

.get_serializer_for(klass, namespace = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Find a serializer from a class and caches the lookup. Preferentially returns:

1. class name appended with "Serializer"
2. try again with superclass, if present
3. nil

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/active_model/serializer.rb', line 82

def self.get_serializer_for(klass, namespace = nil)
  return nil unless config.serializer_lookup_enabled

  cache_key = ActiveSupport::Cache.expand_cache_key(klass, namespace)
  serializers_cache.fetch_or_store(cache_key) do
    # NOTE(beauby): When we drop 1.9.3 support we can lazify the map for perfs.
    lookup_chain = serializer_lookup_chain_for(klass, namespace)
    serializer_class = lookup_chain.map(&:safe_constantize).find { |x| x && x < ActiveModel::Serializer }

    if serializer_class
      serializer_class
    elsif klass.superclass
      get_serializer_for(klass.superclass)
    else
      nil # No serializer found
    end
  end
end

.has_many(name, options = {}, &block) ⇒ void

This method returns an undefined value.

Examples:

has_many :comments, serializer: CommentSummarySerializer

Parameters:

  • name (Symbol)

    of the association

  • options (Hash<Symbol => any>) (defaults to: {})

    for the reflection


233
234
235
# File 'lib/active_model/serializer.rb', line 233

def self.has_many(name, options = {}, &block) # rubocop:disable Style/PredicateName
  associate(HasManyReflection.new(name, options, block))
end

.has_one(name, options = {}, &block) ⇒ void

This method returns an undefined value.

Examples:

has_one :author, serializer: AuthorSerializer

Parameters:

  • name (Symbol)

    of the association

  • options (Hash<Symbol => any>) (defaults to: {})

    for the reflection


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

def self.has_one(name, options = {}, &block) # rubocop:disable Style/PredicateName
  associate(HasOneReflection.new(name, options, block))
end

.include_directive_from_options(options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


102
103
104
105
106
107
108
109
110
# File 'lib/active_model/serializer.rb', line 102

def self.include_directive_from_options(options)
  if options[:include_directive]
    options[:include_directive]
  elsif options[:include]
    JSONAPI::IncludeDirective.new(options[:include], allow_wildcard: true)
  else
    ActiveModelSerializers.default_include_directive
  end
end

.inherited(base) ⇒ Object


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

def self.inherited(base)
  super
  base._attributes_data = _attributes_data.dup
  base._reflections = _reflections.dup
  base._links = _links.dup
end

Define a link on a serializer.

Examples:

link(:self) { resource_url(object) }
link(:self) { "http://example.com/resource/#{object.id}" }
link :resource, "http://example.com/resource"

278
279
280
# File 'lib/active_model/serializer.rb', line 278

def self.link(name, value = nil, &block)
  _links[name] = block || value
end

.meta(value = nil, &block) ⇒ Object

Set the JSON API meta attribute of a serializer.

Examples:

class AdminAuthorSerializer < ActiveModel::Serializer
  meta { stuff: 'value' }
meta do
  { comment_count: object.comments.count }
end

290
291
292
# File 'lib/active_model/serializer.rb', line 290

def self.meta(value = nil, &block)
  self._meta = block || value
end

.serialization_adapter_instanceObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


113
114
115
# File 'lib/active_model/serializer.rb', line 113

def self.serialization_adapter_instance
  @serialization_adapter_instance ||= ActiveModelSerializers::Adapter::Attributes
end

.serializer_for(resource_or_class, options = {}) ⇒ ActiveModel::Serializer

Returns Preferentially returns

  1. resource.serializer_class

  2. ArraySerializer when resource is a collection

  3. options

  4. lookup serializer when resource is a Class.

Parameters:

Returns:

  • (ActiveModel::Serializer)

    Preferentially returns

    1. resource.serializer_class

    2. ArraySerializer when resource is a collection

    3. options

    4. lookup serializer when resource is a Class


41
42
43
44
45
46
47
48
49
50
# File 'lib/active_model/serializer.rb', line 41

def self.serializer_for(resource_or_class, options = {})
  if resource_or_class.respond_to?(:serializer_class)
    resource_or_class.serializer_class
  elsif resource_or_class.respond_to?(:to_ary)
    config.collection_serializer
  else
    resource_class = resource_or_class.class == Class ? resource_or_class : resource_or_class.class
    options.fetch(:serializer) { get_serializer_for(resource_class, options[:namespace]) }
  end
end

.serializer_lookup_chain_for(klass, namespace = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


63
64
65
66
67
68
# File 'lib/active_model/serializer.rb', line 63

def self.serializer_lookup_chain_for(klass, namespace = nil)
  lookups = ActiveModelSerializers.config.serializer_lookup_chain
  Array[*lookups].flat_map do |lookup|
    lookup.call(klass, self, namespace)
  end.compact
end

.serializers_cacheObject

Used to cache serializer name => serializer class when looked up by Serializer.get_serializer_for.


72
73
74
# File 'lib/active_model/serializer.rb', line 72

def self.serializers_cache
  @serializers_cache ||= ThreadSafe::Cache.new
end

.type(type) ⇒ Object

Set the JSON API type of a serializer.

Examples:

class AdminAuthorSerializer < ActiveModel::Serializer
  type 'authors'

298
299
300
# File 'lib/active_model/serializer.rb', line 298

def self.type(type)
  self._type = type && type.to_s
end

Instance Method Details

#as_json(adapter_opts = nil) ⇒ Object

See Also:


367
368
369
# File 'lib/active_model/serializer.rb', line 367

def as_json(adapter_opts = nil)
  serializable_hash(adapter_opts)
end

#associations(include_directive = ActiveModelSerializers.default_include_directive, include_slice = nil) ⇒ Enumerator<Association>

Parameters:

  • include_directive (JSONAPI::IncludeDirective) (defaults to: ActiveModelSerializers.default_include_directive)

    (defaults to the default_include_directive config value when not provided)

Returns:


338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/active_model/serializer.rb', line 338

def associations(include_directive = ActiveModelSerializers.default_include_directive, include_slice = nil)
  include_slice ||= include_directive
  return Enumerator.new unless object

  Enumerator.new do |y|
    self.class._reflections.each do |key, reflection|
      next if reflection.excluded?(self)
      next unless include_directive.key?(key)

      association = reflection.build_association(self, instance_options, include_slice)
      y.yield association
    end
  end
end

#associations_hash(adapter_options, options, adapter_instance) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


396
397
398
399
400
401
402
403
# File 'lib/active_model/serializer.rb', line 396

def associations_hash(adapter_options, options, adapter_instance)
  include_directive = options.fetch(:include_directive)
  include_slice = options[:include_slice]
  associations(include_directive, include_slice).each_with_object({}) do |association, relationships|
    adapter_opts = adapter_options.merge(include_directive: include_directive[association.key], adapter_instance: adapter_instance)
    relationships[association.key] = association.serializable_hash(adapter_opts, adapter_instance)
  end
end

#attributes(requested_attrs = nil, reload = false) ⇒ Object

Return the attributes of object as presented by the serializer.


326
327
328
329
330
331
332
333
# File 'lib/active_model/serializer.rb', line 326

def attributes(requested_attrs = nil, reload = false)
  @attributes = nil if reload
  @attributes ||= self.class._attributes_data.each_with_object({}) do |(key, attr), hash|
    next if attr.excluded?(self)
    next unless requested_attrs.nil? || requested_attrs.include?(key)
    hash[key] = attr.value(self)
  end
end

#attributes_hash(_adapter_options, options, adapter_instance) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.


385
386
387
388
389
390
391
392
393
# File 'lib/active_model/serializer.rb', line 385

def attributes_hash(_adapter_options, options, adapter_instance)
  if self.class.cache_enabled?
    fetch_attributes(options[:fields], options[:cached_attributes] || {}, adapter_instance)
  elsif self.class.fragment_cache_enabled?
    fetch_attributes_fragment(adapter_instance, options[:cached_attributes] || {})
  else
    attributes(options[:fields], true)
  end
end

#json_keyObject

Used by adapter as resource root.


372
373
374
# File 'lib/active_model/serializer.rb', line 372

def json_key
  root || _type || object.class.model_name.to_s.underscore
end

#read_attribute_for_serialization(attr) ⇒ Object


376
377
378
379
380
381
382
# File 'lib/active_model/serializer.rb', line 376

def read_attribute_for_serialization(attr)
  if respond_to?(attr)
    send(attr)
  else
    object.read_attribute_for_serialization(attr)
  end
end

#serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance) ⇒ Hash Also known as: to_hash, to_h

associations, similar to how ActiveModel::Serializers::JSON is used in ActiveRecord::Base.

Returns:

  • (Hash)

    containing the attributes and first level


356
357
358
359
360
361
362
# File 'lib/active_model/serializer.rb', line 356

def serializable_hash(adapter_options = nil, options = {}, adapter_instance = self.class.serialization_adapter_instance)
  adapter_options ||= {}
  options[:include_directive] ||= ActiveModel::Serializer.include_directive_from_options(adapter_options)
  resource = attributes_hash(adapter_options, options, adapter_instance)
  relationships = associations_hash(adapter_options, options, adapter_instance)
  resource.merge(relationships)
end

#success?Boolean

Returns:

  • (Boolean)

320
321
322
# File 'lib/active_model/serializer.rb', line 320

def success?
  true
end