class Mongoid::Association::Nested::One

Builder class used to perform accepts_nested_attributes_for attribute assignment on one-to-n associations.

Attributes

destroy[RW]

Public Class Methods

new(association, attributes, options) click to toggle source

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

build(parent) click to toggle source

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

acceptable_id?() click to toggle source

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
check_for_id_violation!() click to toggle source

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
class_from(name_or_class) click to toggle source

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
delete?() click to toggle source

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
destroyable?() click to toggle source

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
extracted_id() click to toggle source

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
replace?() click to toggle source

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
update?() click to toggle source

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