active_model_serializers/lib/active_model/serializer.rb
Jason Truluck a110df6caf Add @options back into serializers to maintain the functionality of render :json as noted in the docs
This functionality used to exist in v0.8.1. This adds the ability to
pass other options that will be usable in the serializer via the
options accessor.

This works by adding an attr_accessor for options so it is available
and is set by the remaining options in the provided options hash during
initialization.
2013-11-12 12:57:31 -05:00

180 lines
4.9 KiB
Ruby

require 'active_model/array_serializer'
require 'active_model/serializable'
require 'active_model/serializer/associations'
require 'active_model/serializer/config'
require 'thread'
module ActiveModel
class Serializer
include Serializable
@mutex = Mutex.new
class << self
def inherited(base)
base._attributes = []
base._associations = {}
end
def setup
@mutex.synchronize do
yield CONFIG
end
end
def embed(type, options={})
CONFIG.embed = type
CONFIG.embed_in_root = true if options[:embed_in_root] || options[:include]
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
if RUBY_VERSION >= '2.0'
def serializer_for(resource)
if resource.respond_to?(:to_ary)
ArraySerializer
else
begin
Object.const_get "#{resource.class.name}Serializer"
rescue NameError
nil
end
end
end
else
def serializer_for(resource)
if resource.respond_to?(:to_ary)
ArraySerializer
else
"#{resource.class.name}Serializer".safe_constantize
end
end
end
attr_accessor :_root, :_attributes, :_associations
alias root _root=
alias root= _root=
def root_name
name.demodulize.underscore.sub(/_serializer$/, '') if name
end
def attributes(*attrs)
@_attributes.concat attrs
attrs.each do |attr|
define_method attr do
object.read_attribute_for_serialization attr
end unless method_defined?(attr)
end
end
def has_one(*attrs)
associate(Association::HasOne, *attrs)
end
def has_many(*attrs)
associate(Association::HasMany, *attrs)
end
private
def associate(klass, *attrs)
options = attrs.extract_options!
attrs.each do |attr|
define_method attr do
object.send attr
end unless method_defined?(attr)
@_associations[attr] = klass.new(attr, options)
end
end
end
def initialize(object, options={})
@object = object
@scope = options[:scope]
@root = options.fetch(:root, self.class._root)
@meta_key = options[:meta_key] || :meta
@meta = options[@meta_key]
@options = options.reject{|k,v| [:scope, :root, :meta_key, :meta].include?(k) }
end
attr_accessor :object, :scope, :meta_key, :meta, :root, :options
def json_key
if root == true || root.nil?
self.class.root_name
else
root
end
end
def attributes
filter(self.class._attributes.dup).each_with_object({}) do |name, hash|
hash[name] = send(name)
end
end
def associations
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?
hash[association.key] = serialize_ids association
elsif association.embed_objects?
associated_data = send(association.name)
hash[association.embedded_key] = serialize(association, associated_data)
end
end
end
end
def filter(keys)
keys
end
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
if association.embed_in_root?
associated_data = Array(send(association.name))
hash[association.root_key] = serialize(association, associated_data)
end
end
end
end
def serialize(association, object)
association.build_serializer(object, scope: scope).serializable_object
end
def serialize_ids(association)
associated_data = send(association.name)
if associated_data.respond_to?(:to_ary)
associated_data.map { |elem| elem.read_attribute_for_serialization(association.embed_key) }
else
associated_data.read_attribute_for_serialization(association.embed_key) if associated_data
end
end
def serializable_hash(options={})
return nil if object.nil?
hash = attributes
hash.merge! associations
end
alias_method :serializable_object, :serializable_hash
end
end