class Mongoid::Relations::Builders::NestedAttributes::Many
Public Class Methods
Create the new builder for nested attributes on one-to-many relations.
@example Initialize the builder.
One.new(metadata, attributes, options)
@param [ Metadata ] metadata The relation metadata. @param [ Hash ] attributes The attributes hash to attempt to set. @param [ Hash ] options The options defined.
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 43 def initialize(metadata, attributes, options = {}) if attributes.respond_to?(:with_indifferent_access) @attributes = attributes.with_indifferent_access.sort do |a, b| a[0].to_i <=> b[0].to_i end else @attributes = attributes end @metadata = metadata @options = options end
Public Instance Methods
Builds the relation depending on the attributes and the options passed to the macro.
This attempts to perform 3 operations, either one of an update of the existing relation, a replacement of the relation with a new document, or a removal of the relation.
@example Build the nested attrs.
many.build(person)
@param [ Document ] parent The parent document of the relation.
@return [ Array ] The attributes.
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 20 def build(parent, options = {}) @existing = parent.send(metadata.name) if over_limit?(attributes) raise Errors::TooManyNestedAttributeRecords.new(existing, options[:limit]) end attributes.each do |attrs| if attrs.is_a?(::Hash) process_attributes(parent, attrs.with_indifferent_access) else process_attributes(parent, attrs[1].with_indifferent_access) end end end
Private Instance Methods
Destroy the child document, needs to do some checking for embedded relations and delay the destroy in case parent validation fails.
@api private
@example Destroy the child.
builder.destroy(parent, relation, doc)
@param [ Document ] parent The parent document. @param [ Proxy ] relation The relation proxy. @param [ Document ] doc The doc to destroy.
@since 3.0.10
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 125 def destroy(parent, relation, doc) doc.flagged_for_destroy = true if !doc.embedded? || parent.new_record? destroy_document(relation, doc) else parent.flagged_destroys.push(->{ destroy_document(relation, doc) }) end end
Destroy the document.
@api private
@example Destroy the document.
builder.destroy_document(relation, doc)
@param [ Proxy ] relation The relation proxy. @param [ Document ] doc The document to delete.
@since 3.0.10
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 145 def destroy_document(relation, doc) relation.delete(doc) doc.destroy unless doc.embedded? || doc.destroyed? end
Can the existing relation potentially be deleted?
@example Is the document destroyable?
destroyable?({ :_destroy => "1" })
@parma [ Hash ] attributes The attributes to pull the flag from.
@return [ true, false ] If the relation can potentially be deleted.
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 65 def destroyable?(attributes) destroy = attributes.delete(:_destroy) [ 1, "1", true, "true" ].include?(destroy) && allow_destroy? end
Are the supplied attributes of greater number than the supplied limit?
@example Are we over the set limit?
builder.over_limit?({ "street" => "Bond" })
@param [ Hash ] attributes The attributes being set.
@return [ true, false ] If the attributes exceed the limit.
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 79 def over_limit?(attributes) limit = options[:limit] limit ? attributes.size > limit : false end
Process each set of attributes one at a time for each potential new, existing, or ignored document.
@api private
@example Process the attributes
builder.process_attributes({ "id" => 1, "street" => "Bond" })
@param [ Document ] parent The parent document. @param [ Hash ] attrs The single document attributes to process.
@since 2.0.0
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 96 def process_attributes(parent, attrs) return if reject?(parent, attrs) if id = attrs.extract_id first = existing.first converted = first ? convert_id(first.class, id) : id doc = existing.find(converted) if destroyable?(attrs) destroy(parent, existing, doc) else update_document(doc, attrs) end else existing.push(Factory.build(metadata.klass, attrs)) unless destroyable?(attrs) end end
Update the document.
@api private
@example Update the document.
builder.update_document(doc, {}, options)
@param [ Document ] doc The document to update. @param [ Hash ] attrs The attributes.
@since 3.0.10
# File lib/mongoid/relations/builders/nested_attributes/many.rb, line 161 def update_document(doc, attrs) attrs.delete_id if metadata.embedded? doc.assign_attributes(attrs) else doc.update_attributes(attrs) end end