class Mongoid::Association::Nested::One
Builder class used to perform accepts_nested_attributes_for attribute assignment on one-to-n associations.
Attributes
Public Class Methods
Create the new builder for nested attributes on one-to-one associations.
@example Instantiate the builder.
One.new(association, attributes)
@param [ Mongoid::Association::Relatable
] association The association metadata. @param [ Hash ] attributes The attributes hash to attempt to set. @param [ Hash ] options The options defined.
# File lib/mongoid/association/nested/one.rb, line 52 def initialize(association, attributes, options) @attributes = attributes.with_indifferent_access @association = association @options = options @class_name = class_from(options[:class_name]) @destroy = @attributes.delete(:_destroy) end
Public Instance Methods
Builds the association depending on the attributes and the options passed to the macro.
@example Build a 1-1 nested document.
one.build(person, as: :admin)
@note This attempts to perform 3 operations, either one of an update of
the existing association, a replacement of the association with a new document, or a removal of the association.
@param [ Document
] parent The parent document.
@return [ Document
] The built document.
# File lib/mongoid/association/nested/one.rb, line 28 def build(parent) return if reject?(parent, attributes) @existing = parent.send(association.name) if update? delete_id(attributes) existing.assign_attributes(attributes) elsif replace? parent.send(association.setter, Factory.build(@class_name, attributes)) elsif delete? parent.send(association.setter, nil) else check_for_id_violation! end end
Private Instance Methods
Is the id in the attributes acceptable for allowing an update to the existing association?
@api private
@example Is the id acceptable?
one.acceptable_id?
@return [ true | false ] If the id part of the logic will allow an update.
# File lib/mongoid/association/nested/one.rb, line 95 def acceptable_id? id = extracted_id existing._id == id || id.nil? || (existing._id != id && update_only?) end
Checks to see if the _id attribute (which is supposed to be immutable) is being asked to change. If so, raise an exception.
If Mongoid::Config.immutable_ids is false, this will do nothing, and the update operation will fail silently.
@raise [ Errors::ImmutableAttribute
] if _id has changed, and
the document has been persisted.
# File lib/mongoid/association/nested/one.rb, line 150 def check_for_id_violation! # look for the basic criteria of an update (see #update?) return unless existing&.persisted? && !destroyable? # if the id is either absent, or if it equals the existing record's # id, there is no immutability violation. id = extracted_id return if existing._id == id || id.nil? # otherwise, an attempt has been made to set the _id of an existing, # persisted document. if Mongoid::Config.immutable_ids raise Errors::ImmutableAttribute.new(:_id, id) else Mongoid::Warnings.warn_mutable_ids end end
Coerces the argument into a class, or defaults to the association’s class.
@param [ String | Mongoid::Document
| nil ] name_or_class the value to coerce
@return [ Mongoid::Document
] the resulting class
# File lib/mongoid/association/nested/one.rb, line 67 def class_from(name_or_class) case name_or_class when nil, false then association.klass when String then name_or_class.constantize else name_or_class end end
Can the existing association be deleted?
@example Can the existing object be deleted?
one.delete?
@return [ true | false ] If the association should be deleted.
# File lib/mongoid/association/nested/one.rb, line 106 def delete? id = association.klass.extract_id_field(attributes) destroyable? && !id.nil? end
Can the existing association potentially be destroyed?
@example Is the object destroyable?
one.destroyable?({ :_destroy => "1" })
@return [ true | false ] If the association can potentially be
destroyed.
# File lib/mongoid/association/nested/one.rb, line 118 def destroyable? Nested::DESTROY_FLAGS.include?(destroy) && allow_destroy? end
Extracts and converts the id to the expected type.
@return [ BSON::ObjectId | String | Object
| nil ] The converted id,
or nil if no id is present in the attributes hash.
# File lib/mongoid/association/nested/one.rb, line 79 def extracted_id @extracted_id ||= begin id = association.klass.extract_id_field(attributes) convert_id(existing.class, id) end end
Is the document to be replaced?
@example Is the document to be replaced?
one.replace?
@return [ true | false ] If the document should be replaced.
# File lib/mongoid/association/nested/one.rb, line 128 def replace? !existing && !destroyable? && !attributes.blank? end
Should the document be updated?
@example Should the document be updated?
one.update?
@return [ true | false ] If the object should have its attributes updated.
# File lib/mongoid/association/nested/one.rb, line 138 def update? existing && !destroyable? && acceptable_id? end