lib/mongoid/serialization.rb in mongoid-3.0.0.rc vs lib/mongoid/serialization.rb in mongoid-3.0.0
- old
+ new
@@ -25,45 +25,114 @@
# @return [ Hash ] The document, ready to be serialized.
#
# @since 2.0.0.rc.6
def serializable_hash(options = nil)
options ||= {}
+ attrs = {}
- only = Array.wrap(options[:only]).map(&:to_s)
- except = Array.wrap(options[:except]).map(&:to_s)
+ names = field_names(options)
- except |= ['_type'] unless Mongoid.include_type_for_serialization
+ _serializing do
+ method_names = Array.wrap(options[:methods]).map do |name|
+ name.to_s if respond_to?(name)
+ end.compact
- field_names = self.class.attribute_names
- attribute_names = (as_document.keys + field_names).sort
- if only.any?
- attribute_names &= only
- elsif except.any?
- attribute_names -= except
- end
-
- method_names = Array.wrap(options[:methods]).map do |name|
- name.to_s if respond_to?(name)
- end.compact
-
- attrs = {}
- (attribute_names + method_names).each do |name|
- without_autobuild do
- if relations.has_key?(name)
- value = send(name)
- attrs[name] = value ? value.serializable_hash(options) : nil
- elsif attribute_names.include?(name) && !fields.has_key?(name)
- attrs[name] = read_attribute(name)
- else
- attrs[name] = send(name)
+ (names + method_names).each do |name|
+ without_autobuild do
+ serialize_attribute(attrs, name, names, options)
end
end
+ serialize_relations(attrs, options) if options[:include]
end
- serialize_relations(attrs, options) if options[:include]
attrs
end
private
+
+ # Enter the serialization block.
+ #
+ # @api private
+ #
+ # @example Begin serialization.
+ # document._serializing do
+ # end
+ #
+ # @return [ Object ] The result of the yield.
+ #
+ # @since 3.0.0
+ def _serializing
+ Threaded.begin("serialization")
+ yield
+ ensure
+ Threaded.exit("serialization")
+ end
+
+ # Are we in a serialization block? We use this to protect multiple
+ # unnecessary calls to #as_document.
+ #
+ # @api private
+ #
+ # @example Are we in serialization?
+ # document._serializing?
+ #
+ # @return [ true, false ] If we are serializing.
+ #
+ # @since 3.0.0
+ def _serializing?
+ Threaded.executing?("serialization")
+ end
+
+ # Get the names of all fields that will be serialized.
+ #
+ # @api private
+ #
+ # @example Get all the field names.
+ # document.send(:field_names)
+ #
+ # @return [ Array<String> ] The names of the fields.
+ #
+ # @since 3.0.0
+ def field_names(options)
+ names = (_serializing? ? attribute_names : as_document.keys + attribute_names).uniq.sort
+
+ only = Array.wrap(options[:only]).map(&:to_s)
+ except = Array.wrap(options[:except]).map(&:to_s)
+ except |= ['_type'] unless Mongoid.include_type_for_serialization
+
+ if !only.empty?
+ names &= only
+ elsif !except.empty?
+ names -= except
+ end
+ names
+ end
+
+ # Serialize a single attribute. Handles relations, fields, and dynamic
+ # attributes.
+ #
+ # @api private
+ #
+ # @example Serialize the attribute.
+ # document.serialize_attribute({}, "id" , [ "id" ])
+ #
+ # @param [ Hash ] attrs The attributes.
+ # @param [ String ] name The attribute name.
+ # @param [ Array<String> ] names The names of all attributes.
+ # @param [ Hash ] options The options.
+ #
+ # @return [ Object ] The attribute.
+ #
+ # @since 3.0.0
+ def serialize_attribute(attrs, name, names, options)
+ if relations.has_key?(name)
+ value = send(name)
+ attrs[name] = value ? value.serializable_hash(options) : nil
+ elsif names.include?(name) && !fields.has_key?(name)
+ attrs[name] = read_attribute(name)
+ else
+ attrs[name] = send(name)
+ end
+ end
# For each of the provided include options, get the relation needed and
# provide it in the hash.
#
# @example Serialize the included relations.