Class: ActiveModel::Serializer

Inherits:
Object
  • Object
show all
Extended by:
ActiveModelSerializers::Deprecate, ActiveSupport::Autoload
Includes:
Associations, Attributes, Caching, Configuration, Links, Meta, Type
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/concerns/meta.rb,
lib/active_model/serializer/concerns/type.rb,
lib/active_model/serializer/concerns/links.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/errors_serializer.rb,
lib/active_model/serializer/adapter/attributes.rb,
lib/active_model/serializer/has_one_reflection.rb,
lib/active_model/serializer/concerns/attributes.rb,
lib/active_model/serializer/has_many_reflection.rb,
lib/active_model/serializer/singular_reflection.rb,
lib/active_model/serializer/belongs_to_reflection.rb,
lib/active_model/serializer/collection_reflection.rb,
lib/active_model/serializer/collection_serializer.rb,
lib/active_model/serializer/concerns/associations.rb,
lib/active_model/serializer/concerns/configuration.rb

Direct Known Subclasses

ErrorSerializer, Null

Defined Under Namespace

Modules: Adapter, Associations, Attributes, Caching, Configuration, Links, Lint, Meta, Type Classes: ArraySerializer, Association, Attribute, BelongsToReflection, CollectionReflection, CollectionSerializer, ErrorSerializer, ErrorsSerializer, Field, Fieldset, HasManyReflection, HasOneReflection, Null, Reflection, SingularReflection

Constant Summary collapse

SERIALIZABLE_HASH_VALID_KEYS =
[:only, :except, :methods, :include, :root].freeze
VERSION =
'0.10.8'.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

Methods included from Associations

#associations

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.



119
120
121
122
123
124
125
126
127
128
# File 'lib/active_model/serializer.rb', line 119

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

Returns the value of attribute object.



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

def object
  @object
end

#rootObject

Returns the value of attribute root.



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

def root
  @root
end

#scopeObject

Returns the value of attribute scope.



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

def scope
  @scope
end

Class Method Details

.adapterObject

Deprecated



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

def self.adapter
  ActiveModelSerializers::Adapter.lookup(config.adapter)
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


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

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)
    end
  end
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.



99
100
101
102
103
104
105
106
107
# File 'lib/active_model/serializer.rb', line 99

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

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



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

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

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

Returns Preferentially returns

  1. resource.serializer

  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

    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
# File 'lib/active_model/serializer.rb', line 41

def self.serializer_for(resource, options = {})
  if resource.respond_to?(:serializer_class)
    resource.serializer_class
  elsif resource.respond_to?(:to_ary)
    config.collection_serializer
  else
    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.



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

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.



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

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

Instance Method Details

#as_json(adapter_opts = nil) ⇒ Object

TODO: When moving attributes adapter logic here, @see #serializable_hash So that the below is true:

@param options [nil, Hash] The same valid options passed to `as_json`
   (:root, :only, :except, :methods, and :include).
The default for `root` is nil.
The default value for include_root is false. You can change it to true if the given
JSON string includes a single root node.

See Also:



181
182
183
# File 'lib/active_model/serializer.rb', line 181

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

#json_keyObject

Used by adapter as resource root.



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

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

#read_attribute_for_serialization(attr) ⇒ Object



190
191
192
193
194
195
196
# File 'lib/active_model/serializer.rb', line 190

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

#relationship_value_for(association, adapter_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.



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/active_model/serializer.rb', line 211

def relationship_value_for(association, adapter_options, adapter_instance)
  return association.options[:virtual_value] if association.options[:virtual_value]
  association_serializer = association.serializer
  association_object = association_serializer && association_serializer.object
  return unless association_object

  relationship_value = association_serializer.serializable_hash(adapter_options, {}, adapter_instance)

  if association.options[:polymorphic] && relationship_value
    polymorphic_type = association_object.class.name.underscore
    relationship_value = { type: polymorphic_type, polymorphic_type.to_sym => relationship_value }
  end

  relationship_value
end

#resource_relationships(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.



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

def resource_relationships(adapter_options, options, adapter_instance)
  relationships = {}
  include_directive = options.fetch(:include_directive)
  associations(include_directive).each do |association|
    adapter_opts = adapter_options.merge(include_directive: include_directive[association.key])
    relationships[association.key] ||= relationship_value_for(association, adapter_opts, adapter_instance)
  end

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

TODO: Include ActiveModel::Serializers::JSON. So that the below is true:

@param options [nil, Hash] The same valid options passed to `serializable_hash`
   (:only, :except, :methods, and :include).

  See
  https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serializers/json.rb#L17-L101
  https://github.com/rails/rails/blob/v5.0.0.beta2/activemodel/lib/active_model/serialization.rb#L85-L123
  https://github.com/rails/rails/blob/v5.0.0.beta2/activerecord/lib/active_record/serialization.rb#L11-L17
  https://github.com/rails/rails/blob/v5.0.0.beta2/activesupport/lib/active_support/core_ext/object/json.rb#L147-L162

@example
  # The :only and :except options can be used to limit the attributes included, and work
  # similar to the attributes method.
  serializer.as_json(only: [:id, :name])
  serializer.as_json(except: [:id, :created_at, :age])

  # To include the result of some method calls on the model use :methods:
  serializer.as_json(methods: :permalink)

  # To include associations use :include:
  serializer.as_json(include: :posts)
  # Second level and higher order associations work as well:
  serializer.as_json(include: { posts: { include: { comments: { only: :body } }, only: :title } })

Returns:

  • (Hash)

    containing the attributes and first level



162
163
164
165
166
167
168
169
# File 'lib/active_model/serializer.rb', line 162

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)
  cached_attributes = adapter_options[:cached_attributes] ||= {}
  resource = fetch_attributes(options[:fields], cached_attributes, adapter_instance)
  relationships = resource_relationships(adapter_options, options, adapter_instance)
  resource.merge(relationships)
end

#success?Boolean

Returns:

  • (Boolean)


130
131
132
# File 'lib/active_model/serializer.rb', line 130

def success?
  true
end