# frozen_string_literal: truerequire'active_model/array_serializer'require'active_model/serializable'require'active_model/serializer/association'require'active_model/serializer/config'require'thread'require'concurrent/map'moduleActiveModelclassSerializerincludeSerializable@mutex=Mutex.newclass<<selfdefinherited(base)base._root=_rootbase._attributes=(_attributes||[]).dupbase._associations=(_associations||{}).dupenddefsetup@mutex.synchronizedoyieldCONFIGendendEMBED_IN_ROOT_OPTIONS=[:include,:embed_in_root,:embed_in_root_key,:embed_namespace].freezedefembed(type,options={})CONFIG.embed=typeifEMBED_IN_ROOT_OPTIONS.any?{|opt|options[opt].present?}CONFIG.embed_in_root=trueendifoptions[:embed_in_root_key].present?CONFIG.embed_in_root_key=options[:embed_in_root_key]endActiveSupport::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
WARNenddefformat_keys(format)@key_format=formatendattr_reader:key_formatdefserializer_for(resource,options={})ifresource.respond_to?(:serializer_class)resource.serializer_classelsifresource.respond_to?(:to_ary)ifdefined?(::ArraySerializer)::ArraySerializerelseArraySerializerendelseeach_possible_serializer(resource,options)do|klass_name|serializer=Serializer.serializers_cache.fetch_or_store(klass_name)do_const_get(klass_name)endreturnserializerunlessserializer.nil?endnilendendattr_accessor:_root,:_attributes,:_associationsaliasroot_root=aliasroot=_root=defroot_nameifnameroot_name=name.demodulize.underscore.sub(/_serializer$/,'')CONFIG.plural_default_root?root_name.pluralize:root_nameendenddefattributes(*attrs)attrs.eachdo|attr|striped_attr=strip_attributeattr@_attributes<<striped_attrdefine_methodstriped_attrdoobject.read_attribute_for_serializationattrendunlessmethod_defined?(attr)endenddefhas_one(*attrs)associate(Association::HasOne,*attrs)enddefhas_many(*attrs)associate(Association::HasMany,*attrs)enddefserializers_cache@serializers_cache||=Concurrent::Map.newendprivatedefstrip_attribute(attr)symbolized=attr.is_a?(Symbol)attr=attr.to_s.gsub(/\?\Z/,'')attr=attr.to_symifsymbolizedattrenddefeach_possible_serializer(resource,options)yieldbuild_serializer_class(resource,options)yieldbuild_serializer_class(resource,{})yieldbuild_serializer_class(resource.class.name.demodulize,{})enddefbuild_serializer_class(resource,options)klass_name=+""klass_name<<"#{options[:namespace]}::"ifoptions[:namespace]klass_name<<options[:prefix].to_s.classifyifoptions[:prefix]klass_name<<"#{resource.class.name}Serializer"enddefassociate(klass,*attrs)options=attrs.extract_options!attrs.eachdo|attr|define_methodattrdoobject.sendattrendunlessmethod_defined?(attr)@_associations[attr]=klass.new(attr,options)endendenddefinitialize(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]endattr_accessor:object,:scope,:root,:meta_key,:meta,:context,:polymorphicattr_writer:key_formatdefjson_keykey=ifroot==true||root.nil?self.class.root_nameelserootendkey_format==:lower_camel&&key.present??key.camelize(:lower):keyenddefattributesfilter(self.class._attributes.dup).each_with_object({})do|name,hash|hash[name]=send(name)endenddefassociations(options={})associations=self.class._associationsincluded_associations=filter(associations.keys)associations.each_with_object({})do|(name,association),hash|ifincluded_associations.include?nameifassociation.embed_ids?ids=serialize_idsassociationifassociation.embed_namespace?hash=hash[association.embed_namespace]||={}hash[association.key]=idselsehash[association.key]=idsendelsifassociation.embed_objects?ifassociation.embed_namespace?hash=hash[association.embed_namespace]||={}endhash[association.embedded_key]=serializeassociation,optionsendendendenddeffilter(keys)if@onlykeys&@onlyelsif@exceptkeys-@exceptelsekeysendenddefembedded_in_root_associationsassociations=self.class._associationsincluded_associations=filter(associations.keys)associations.each_with_object({})do|(name,association),hash|ifincluded_associations.include?nameassociation_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 roothash.merge!(association_serializer.embedded_in_root_associations)do|key,oldval,newval|ifoldval.respond_to?(:to_ary)[oldval,newval].flatten.uniqelseoldval.merge(newval){|_,oldval,newval|[oldval,newval].flatten.uniq}endendifassociation.embed_in_root?ifassociation.embed_in_root_key?hash=hash[association.embed_in_root_key]||={}endserialized_data=association_serializer.serializable_objectkey=association.root_keyifhash.has_key?(key)hash[key].concat(serialized_data).uniq!elsehash[key]=serialized_dataendendendendenddefbuild_serializer(association)object=send(association.name)association.build_serializer(object,association_options_for_serializer(association))enddefassociation_options_for_serializer(association)prefix=association.options[:prefix]namespace=association.options[:namespace]||@namespace||self.namespace{scope: scope}.tapdo|opts|opts[:namespace]=namespaceifnamespaceopts[:prefix]=prefixifprefixendenddefserialize(association,options={})build_serializer(association).serializable_object(options)enddefserialize_ids(association)associated_data=send(association.name)ifassociated_data.respond_to?(:to_ary)associated_data.map{|elem|serialize_id(elem,association)}elseserialize_id(associated_data,association)ifassociated_dataendenddefkey_format@key_format||self.class.key_format||CONFIG.key_formatenddefformat_key(key)ifkey_format==:lower_camelkey.to_s.camelize(:lower)elsekeyendenddefconvert_keys(hash)Hash[hash.mapdo|k,v|key=ifk.is_a?(Symbol)format_key(k).to_symelseformat_key(k)end[key,v]end]endattr_writer:serialization_optionsdefserialization_options@serialization_options||{}enddefserializable_object(options={})self.serialization_options=optionsreturn@wrap_in_array?[]:nilif@object.nil?hash=attributeshash.merge!associations(options)hash=convert_keys(hash)ifkey_format.present?hash={:type=>type_name(@object),type_name(@object)=>hash}if@polymorphic@wrap_in_array?[hash]:hashendalias_method:serializable_hash,:serializable_objectdefserialize_id(elem,association)id=elem.read_attribute_for_serialization(association.embed_key)association.polymorphic??{id: id,type: type_name(elem)}:idenddeftype_name(elem)elem.class.to_s.demodulize.underscore.to_symendendend