module Mongoid::Attributes

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

Attributes

attributes[R]
raw_attributes[R]

Public Instance Methods

[](name)
Alias for: read_attribute
[]=(name, value)
Alias for: write_attribute
assign_attributes(attrs = nil) click to toggle source

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.

@example Assign the attributes.

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

@example Assign the attributes (with a role).

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

@param [ Hash ] attrs The new attributes to set.

# File lib/mongoid/attributes.rb, line 218
def assign_attributes(attrs = nil)
  _assigning do
    process_attributes(attrs)
  end
end
attribute_missing?(name) click to toggle source

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

@example Is the attribute missing?

document.attribute_missing?("test")

@param [ String ] name The name of the attribute.

@return [ true | false ] If the attribute is missing.

# File lib/mongoid/attributes.rb, line 249
def attribute_missing?(name)
  !Projector.new(__selected_fields).attribute_or_path_allowed?(name)
end
attribute_present?(name) click to toggle source

Determine if an attribute is present.

@example Is the attribute present?

person.attribute_present?("title")

@param [ String | Symbol ] name The name of the attribute.

@return [ true | false ] True if present, false if not.

# 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=(attrs = nil)
Alias for: write_attributes
attributes_before_type_cast() click to toggle source

Get the attributes that have not been cast.

@example Get the attributes before type cast.

document.attributes_before_type_cast

@return [ Hash ] The uncast attributes.

# File lib/mongoid/attributes.rb, line 46
def attributes_before_type_cast
  @attributes_before_type_cast ||= {}
end
has_attribute?(name) click to toggle source

Does the document have the provided attribute?

@example Does the document have the attribute?

model.has_attribute?(:name)

@param [ String | Symbol ] name The name of the attribute.

@return [ true | false ] If the key is present in the attributes.

# File lib/mongoid/attributes.rb, line 58
def has_attribute?(name)
  attributes.key?(name.to_s)
end
has_attribute_before_type_cast?(name) click to toggle source

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

@example Does the document have the attribute before it was assigned?

model.has_attribute_before_type_cast?(:name)

@param [ String | Symbol ] name The name of the attribute.

@return [ true | false ] If the key is present in the

attributes_before_type_cast.
# File lib/mongoid/attributes.rb, line 72
def has_attribute_before_type_cast?(name)
  attributes_before_type_cast.key?(name.to_s)
end
process_raw_attribute(name, raw, field) click to toggle source

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

@param [ String ] name The name of the attribute to get. @param [ Object ] raw The raw attribute value. @param [ Field | nil ] field The field to use for demongoization or nil.

@return [ Object ] The value of the attribute.

@api private

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

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

@example Read an attribute.

person.read_attribute(:title)

@example Read an attribute (alternate syntax.)

person[:title]

@param [ String | Symbol ] name The name of the attribute to get.

@return [ Object ] The value of the attribute.

# 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
Also aliased as: []
read_attribute_before_type_cast(name) click to toggle source

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.

@example Read an attribute before type cast.

person.read_attribute_before_type_cast(:price)

@param [ String | Symbol ] name The name of the attribute to get.

@return [ Object ] The value of the attribute before type cast, if

available. Otherwise, the value of the attribute.
# 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
remove_attribute(name) click to toggle source

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

@example Remove the attribute.

person.remove_attribute(:title)

@param [ String | Symbol ] name The name of the attribute to remove.

@raise [ Errors::ReadonlyAttribute ] If the field cannot be removed due

to being flagged as reaodnly.
# 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_attributes() click to toggle source

Return type-casted attributes.

@example Type-casted attributes.

document.typed_attributes

@return [ Object ] The hash with keys and values of the type-casted attributes.

# File lib/mongoid/attributes.rb, line 259
def typed_attributes
  attribute_names.map { |name| [name, send(name)] }.to_h
end
write_attribute(name, value) click to toggle source

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

@example Write the attribute.

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

@example Write the attribute (alternate syntax.)

person[:title] = "Mr."

@param [ String | Symbol ] name The name of the attribute to update. @param [ Object ] value The value to set for the attribute.

# 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
Also aliased as: []=
write_attributes(attrs = nil) click to toggle source

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.

@example Write the attributes.

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

@example Write the attributes (alternate syntax.)

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

@param [ Hash ] attrs The new attributes to set.

# File lib/mongoid/attributes.rb, line 235
def write_attributes(attrs = nil)
  assign_attributes(attrs)
end
Also aliased as: attributes=

Private Instance Methods

hash_dot_syntax?(string) click to toggle source

Does the string contain dot syntax for accessing hashes?

@api private

@example Is the string in dot syntax.

model.hash_dot_syntax?

@return [ true | false ] If the string contains a “.”

# File lib/mongoid/attributes.rb, line 273
def hash_dot_syntax?(string)
  string.include?(".")
end
lookup_attribute_presence(name, value) click to toggle source
# 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
read_raw_attribute(name) click to toggle source
# 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
typed_value_for(key, value) click to toggle source

Return the typecasted value for a field.

@example Get the value typecasted.

person.typed_value_for(:title, :sir)

@param [ String | Symbol ] key The field name. @param [ Object ] value The uncast value.

@return [ Object ] The cast value.

# File lib/mongoid/attributes.rb, line 286
def typed_value_for(key, value)
  fields.key?(key) ? fields[key].mongoize(value) : value.mongoize
end