# encoding: utf-8 module Mongoid # :nodoc: # This module provides the extra behaviour for including relations in JSON # and XML serialization. module Serialization extend ActiveSupport::Concern include ActiveModel::Serialization # Gets the document as a serializable hash, used by ActiveModel's JSON and # XML serializers. This override is just to be able to pass the :include # and :except options to get associations in the hash. # # @example Get the serializable hash. # document.serializable_hash # # @example Get the serializable hash with options. # document.serializable_hash(:include => :addresses) # # @param [ Hash ] options The options to pass. # # @option options [ Symbol ] :include What relations to include # @option options [ Symbol ] :only Limit the fields to only these. # @option options [ Symbol ] :except Dont include these fields. # # @return [ Hash ] The document, ready to be serialized. # # @since 2.0.0.rc.6 def serializable_hash(options = nil) options ||= {} super(options).tap do |attrs| serialize_relations(attrs, options) if options[:include] end end private # For each of the provided include options, get the relation needed and # provide it in the hash. # # @example Serialize the included relations. # document.serialize_relations({}, :include => :addresses) # # @param [ Hash ] attributes The attributes to serialize. # @param [ Hash ] options The serialization options. # # @option options [ Symbol ] :include What relations to include # @option options [ Symbol ] :only Limit the fields to only these. # @option options [ Symbol ] :except Dont include these fields. # # @since 2.0.0.rc.6 def serialize_relations(attributes = {}, options = {}) inclusions = options.delete(:include) relation_names(inclusions).each do |name| metadata = relations[name.to_s] relation = send(metadata.name, false, :eager => true) if relation attributes[metadata.name.to_s] = relation.serializable_hash(relation_options(inclusions, options, name)) end end end # Since the inclusions can be a hash, symbol, or array of symbols, this is # provided as a convenience to parse out the names. # # @example Get the relation names. # document.relation_names(:include => [ :addresses ]) # # @param [ Hash, Symbol, Array ] The names of the included relations. # # @since 2.0.0.rc.6 def relation_names(inclusions) inclusions.is_a?(Hash) ? inclusions.keys : Array.wrap(inclusions) end # Since the inclusions can be a hash, symbol, or array of symbols, this is # provided as a convenience to parse out the options. # # @example Get the relation options. # document.relation_names(:include => [ :addresses ]) # # @param [ Hash, Symbol, Array options[:except], :only => options[:only] } end end end end