123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Attributes

Overview

This module contains the logic for handling the internal attributes hash, and how to get and set values.

Nested - Attributes & Methods

Readonly - Attributes & Methods

Class Method Summary

Attributes::Readonly::ClassMethods - Extended

attr_readonly

Defines an attribute as readonly.

Attributes::Nested::ClassMethods - Extended

accepts_nested_attributes_for

Used when needing to update related models from a parent association.

autosave_nested_attributes

Add the autosave information for the nested association.

Instance Attribute Summary

Instance Method Summary

Readonly - Included

#attribute_writable?

Are we able to write the attribute with the provided name?

#_loaded?, #as_writable_attribute!, #projected_field?

Processing - Included

#process_attributes

Process the provided attributes casting them to their proper values if a field exists for them on the document.

#pending_attribute?

If the key provided is the name of an association or a nested attribute, we need to wait until all other attributes are set before processing these.

#pending_nested

Get all the pending nested attributes that need to be set.

#pending_relations

Get all the pending associations that need to be set.

#process_attribute

If the attribute is dynamic, add a field for it with a type of object and then either way set the value.

#process_nested

Process all the pending nested attributes that needed to wait until ids were set to fire off.

#process_pending

Process all the pending items, then clear them out.

#process_relations

Process all the pending associations that needed to wait until ids were set to fire off.

#set_pending_nested

::Set value of the pending nested attribute.

#set_pending_relation

::Set value of the pending relation.

Class Attribute Details

.nested_attributes (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/nested.rb', line 12

class_attribute :nested_attributes

.nested_attributes?Boolean (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/nested.rb', line 12

class_attribute :nested_attributes

.readonly_attributes (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/readonly.rb', line 12

class_attribute :readonly_attributes

.readonly_attributes?Boolean (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/readonly.rb', line 12

class_attribute :readonly_attributes

Instance Attribute Details

#nested_attributes (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/nested.rb', line 12

class_attribute :nested_attributes

#nested_attributes?Boolean (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/nested.rb', line 12

class_attribute :nested_attributes

#raw_attributes (readonly)

Alias for #attributes.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 23

alias :raw_attributes :attributes

#readonly_attributes (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/readonly.rb', line 12

class_attribute :readonly_attributes

#readonly_attributes?Boolean (rw)

[ GitHub ]

  
# File 'lib/mongoid/attributes/readonly.rb', line 12

class_attribute :readonly_attributes

Instance Method Details

#[](name)

Alias for #read_attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 93

alias :[] :read_attribute

#[]=(name, value)

Alias for #write_attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 204

alias :[]= :write_attribute

#assign_attributes(attrs = nil)

Allows you to set all the attributes for a particular mass-assignment security role by passing in a hash of attributes with keys matching the attribute names (which again matches the column names) and the role name using the :as option. To bypass mass-assignment security you can use the :without_protection => true option.

Examples:

Assign the attributes.

person.assign_attributes(:title => "Mr.")

Assign the attributes (with a role).

person.assign_attributes({ :title => "Mr." }, :as => :admin)

Parameters:

  • attrs (Hash) (defaults to: nil)

    The new attributes to set.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 218

def assign_attributes(attrs = nil)
  _assigning do
    process_attributes(attrs)
  end
end

#attribute_missing?(name) ⇒ true | false

Determine if the attribute is missing from the document, due to loading it from the database with missing fields.

Examples:

Is the attribute missing?

document.attribute_missing?("test")

Parameters:

  • name (String)

    The name of the attribute.

Returns:

  • (true | false)

    If the attribute is missing.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 249

def attribute_missing?(name)
  !Projector.new(__selected_fields).attribute_or_path_allowed?(name)
end

#attribute_present?(name) ⇒ true | false

Determine if an attribute is present.

Examples:

Is the attribute present?

person.attribute_present?("title")

Parameters:

Returns:

  • (true | false)

    True if present, false if not.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 33

def attribute_present?(name)
  attribute = read_raw_attribute(name)
  !attribute.blank? || attribute == false
rescue Mongoid::Errors::AttributeNotLoaded
  false
end

#attributes Also known as: #raw_attributes

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 22

attr_reader :attributes

#attributes=(attrs = nil)

Alias for #write_attributes.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 238

alias :attributes= :write_attributes

#attributes_before_type_castHash

Get the attributes that have not been cast.

Examples:

Get the attributes before type cast.

document.attributes_before_type_cast

Returns:

  • (Hash)

    The uncast attributes.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 46

def attributes_before_type_cast
  @attributes_before_type_cast ||= {}
end

#has_attribute?(name) ⇒ true | false

Does the document have the provided attribute?

Examples:

Does the document have the attribute?

model.has_attribute?(:name)

Parameters:

Returns:

  • (true | false)

    If the key is present in the attributes.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 58

def has_attribute?(name)
  attributes.key?(name.to_s)
end

#has_attribute_before_type_cast?(name) ⇒ true | false

Does the document have the provided attribute before it was assigned and type cast?

Examples:

Does the document have the attribute before it was assigned?

model.has_attribute_before_type_cast?(:name)

Parameters:

Returns:

  • (true | false)

    If the key is present in the attributes_before_type_cast.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 72

def has_attribute_before_type_cast?(name)
  attributes_before_type_cast.key?(name.to_s)
end

#hash_dot_syntax?(string) ⇒ true | false (private)

This method is for internal use only.

Does the string contain dot syntax for accessing hashes?

Examples:

Is the string in dot syntax.

model.hash_dot_syntax?

Returns:

  • (true | false)

    If the string contains a “.”

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 273

def hash_dot_syntax?(string)
  string.include?(".")
end

#lookup_attribute_presence(name, value) (private)

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 363

def lookup_attribute_presence(name, value)
  if localized_fields.has_key?(name) && value
    value = localized_fields[name].send(:lookup, value)
  end
  value.present?
end

#process_raw_attribute(name, raw, field) ⇒ Object

This method is for internal use only.

Process the raw attribute values just read from the documents attributes.

Parameters:

  • name (String)

    The name of the attribute to get.

  • raw (Object)

    The raw attribute value.

  • field (Field | nil)

    The field to use for demongoization or nil.

Returns:

  • (Object)

    The value of the attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 105

def process_raw_attribute(name, raw, field)
  value = field ? field.demongoize(raw) : raw
  attribute_will_change!(name) if value.resizable?
  value
end

#read_attribute(name) ⇒ Object Also known as: #[]

Read a value from the document attributes. If the value does not exist it will return nil.

Examples:

Read an attribute.

person.read_attribute(:title)

Read an attribute (alternate syntax.)

person[:title]

Parameters:

  • name (String | Symbol)

    The name of the attribute to get.

Returns:

  • (Object)

    The value of the attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 88

def read_attribute(name)
  field = fields[name.to_s]
  raw = read_raw_attribute(name)
  process_raw_attribute(name.to_s, raw, field)
end

#read_attribute_before_type_cast(name) ⇒ Object

Read a value from the attributes before type cast. If the value has not yet been assigned then this will return the attribute’s existing value using read_raw_attribute.

Examples:

Read an attribute before type cast.

person.read_attribute_before_type_cast(:price)

Parameters:

  • name (String | Symbol)

    The name of the attribute to get.

Returns:

  • (Object)

    The value of the attribute before type cast, if available. Otherwise, the value of the attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 122

def read_attribute_before_type_cast(name)
  attr = name.to_s
  if attributes_before_type_cast.key?(attr)
    attributes_before_type_cast[attr]
  else
    read_raw_attribute(attr)
  end
end

#read_raw_attribute(name) (private)

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 292

def read_raw_attribute(name)
  normalized = database_field_name(name.to_s)

  if attribute_missing?(normalized)
    raise Mongoid::Errors::AttributeNotLoaded.new(self.class, name)
  end

  if hash_dot_syntax?(normalized)
    if fields.key?(normalized)
      attributes[normalized]
    else
      Embedded.traverse(attributes, normalized)
    end
  else
    attributes[normalized]
  end
end

#remove_attribute(name)

Remove a value from the Document attributes. If the value does not exist it will fail gracefully.

Examples:

Remove the attribute.

person.remove_attribute(:title)

Parameters:

  • name (String | Symbol)

    The name of the attribute to remove.

Raises:

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 141

def remove_attribute(name)
  validate_writable_field_name!(name.to_s)
  as_writable_attribute!(name) do |access|
    _assigning do
      attribute_will_change!(access)
      delayed_atomic_unsets[atomic_attribute_name(access)] = [] unless new_record?
      attributes.delete(access)
    end
  end
end

#typed_attributesObject

Return type-casted attributes.

Examples:

Type-casted attributes.

document.typed_attributes

Returns:

  • (Object)

    The hash with keys and values of the type-casted attributes.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 259

def typed_attributes
  attribute_names.map { |name| [name, send(name)] }.to_h
end

#typed_value_for(key, value) ⇒ Object (private)

Return the typecasted value for a field.

Examples:

Get the value typecasted.

person.typed_value_for(:title, :sir)

Parameters:

  • key (String | Symbol)

    The field name.

  • value (Object)

    The uncast value.

Returns:

  • (Object)

    The cast value.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 286

def typed_value_for(key, value)
  fields.key?(key) ? fields[key].mongoize(value) : value.mongoize
end

#write_attribute(name, value) Also known as: #[]=

Write a single attribute to the document attribute hash. This will also fire the before and after update callbacks, and perform any necessary typecasting.

Examples:

Write the attribute.

person.write_attribute(:title, "Mr.")

Write the attribute (alternate syntax.)

person[:title] = "Mr."

Parameters:

  • name (String | Symbol)

    The name of the attribute to update.

  • value (Object)

    The value to set for the attribute.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 164

def write_attribute(name, value)
  validate_writable_field_name!(name.to_s)

  field_name = database_field_name(name)

  if attribute_missing?(field_name)
    raise Mongoid::Errors::AttributeNotLoaded.new(self.class, field_name)
  end

  if attribute_writable?(field_name)
    _assigning do
      localized = fields[field_name].try(:localized?)
      attributes_before_type_cast[name.to_s] = value
      typed_value = typed_value_for(field_name, value)
      unless attributes[field_name] == typed_value || attribute_changed?(field_name)
        attribute_will_change!(field_name)
      end
      if localized
        present = fields[field_name].try(:localize_present?)
        loc_key, loc_val = typed_value.first
        if present && loc_val.blank?
          attributes[field_name]&.delete(loc_key)
        else
          attributes[field_name] ||= {}
          attributes[field_name].merge!(typed_value)
        end
      else
        attributes[field_name] = typed_value
      end

      # when writing an attribute, also remove it from the unsets,
      # so that removing then writing doesn't result in a removal.
      delayed_atomic_unsets.delete(field_name)

      typed_value
    end
  else
    # TODO: MONGOID-5072
  end
end

#write_attributes(attrs = nil) Also known as: #attributes=

Writes the supplied attributes hash to the document. This will only overwrite existing attributes if they are present in the new ::Hash, all others will be preserved.

Examples:

Write the attributes.

person.write_attributes(:title => "Mr.")

Write the attributes (alternate syntax.)

person.attributes = { :title => "Mr." }

Parameters:

  • attrs (Hash) (defaults to: nil)

    The new attributes to set.

[ GitHub ]

  
# File 'lib/mongoid/attributes.rb', line 235

def write_attributes(attrs = nil)
  assign_attributes(attrs)
end