123456789_123456789_123456789_123456789_123456789_

Class: Mongoid::Association::Nested::One

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, Buildable
Inherits: Object
Defined in: lib/mongoid/association/nested/one.rb

Overview

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

Class Method Summary

Instance Attribute Summary

Buildable - Included

#allow_destroy?

Determines if destroys are allowed for this document.

#association, #attributes, #existing, #options,
#update_only?

Determines if only updates can occur.

Instance Method Summary

Buildable - Included

#convert_id

Convert an id to its appropriate type.

#reject?

Returns the reject if option defined with the macro.

#delete_id

Deletes the id key from the given hash.

#extract_id

Get the id attribute from the given hash, whether it’s prefixed with an underscore or is a symbol.

Constructor Details

.new(association, attributes, options) ⇒ One

Create the new builder for nested attributes on one-to-one associations.

Examples:

Instantiate the builder.

One.new(association, attributes)

Parameters:

[ GitHub ]

  
# 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 = options[:class_name] ? options[:class_name].constantize : association.klass
  @destroy = @attributes.delete(:_destroy)
end

Instance Attribute Details

#acceptable_id?true | false (readonly, private)

This method is for internal use only.

Is the id in the attributes acceptable for allowing an update to the existing association?

Examples:

Is the id acceptable?

one.acceptable_id?

Returns:

  • (true | false)

    If the id part of the logic will allow an update.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 82

def acceptable_id?
  id = extracted_id
  existing._id == id || id.nil? || (existing._id != id && update_only?)
end

#delete?true | false (readonly, private)

Can the existing association be deleted?

Examples:

Can the existing object be deleted?

one.delete?

Returns:

  • (true | false)

    If the association should be deleted.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 93

def delete?
  id = association.klass.extract_id_field(attributes)
  destroyable? && !id.nil?
end

#destroy (rw)

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 13

attr_accessor :destroy

#destroyable?true | false (readonly, private)

Can the existing association potentially be destroyed?

Examples:

Is the object destroyable?

one.destroyable?({ :_destroy => "1" })

Returns:

  • (true | false)

    If the association can potentially be destroyed.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 105

def destroyable?
  Nested::DESTROY_FLAGS.include?(destroy) && allow_destroy?
end

#replace?true | false (readonly, private)

Is the document to be replaced?

Examples:

Is the document to be replaced?

one.replace?

Returns:

  • (true | false)

    If the document should be replaced.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 115

def replace?
  !existing && !destroyable? && !attributes.blank?
end

#update?true | false (readonly, private)

Should the document be updated?

Examples:

Should the document be updated?

one.update?

Returns:

  • (true | false)

    If the object should have its attributes updated.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 125

def update?
  existing && !destroyable? && acceptable_id?
end

Instance Method Details

#build(parent) ⇒ Document

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.

Builds the association depending on the attributes and the options passed to the macro.

Examples:

Build a 1-1 nested document.

one.build(person, as: :admin)

Parameters:

  • parent (Document)

    The parent document.

Returns:

[ GitHub ]

  
# 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

#check_for_id_violation! (private)

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.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 137

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

#extracted_idBSON::ObjectId | String | Object | nil (private)

Extracts and converts the id to the expected type.

Returns:

  • (BSON::ObjectId | String | Object | nil)

    The converted id, or nil if no id is present in the attributes hash.

[ GitHub ]

  
# File 'lib/mongoid/association/nested/one.rb', line 66

def extracted_id
  @extracted_id ||= begin
    id = association.klass.extract_id_field(attributes)
    convert_id(existing.class, id)
  end
end