Module: Mongoid::Fields

Extended by:
ActiveSupport::Concern
Included in:
Composable
Defined in:
build/mongoid-8.1/lib/mongoid/fields.rb,
build/mongoid-8.1/lib/mongoid/fields/standard.rb,
build/mongoid-8.1/lib/mongoid/fields/localized.rb,
build/mongoid-8.1/lib/mongoid/fields/foreign_key.rb,
build/mongoid-8.1/lib/mongoid/fields/validators/macro.rb

Overview

This module defines behavior for fields.

Defined Under Namespace

Modules: ClassMethods, Validators Classes: ForeignKey, Localized, Standard

Constant Summary collapse

StringifiedSymbol =
Mongoid::StringifiedSymbol
Boolean =
Mongoid::Boolean
TYPE_MAPPINGS =

For fields defined with symbols use the correct class.

{
  array: Array,
  big_decimal: BigDecimal,
  binary: BSON::Binary,
  boolean: Mongoid::Boolean,
  date: Date,
  date_time: DateTime,
  float: Float,
  hash: Hash,
  integer: Integer,
  object_id: BSON::ObjectId,
  range: Range,
  regexp: Regexp,
  set: Set,
  string: String,
  stringified_symbol: StringifiedSymbol,
  symbol: Symbol,
  time: Time
}.with_indifferent_access
IDS =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Constant for all names of the _id field in a document.

This does not include aliases of _id field.

[ :_id, '_id', ].freeze
INVALID_BSON_CLASSES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

BSON classes that are not supported as field types

[ BSON::Decimal128, BSON::Int32, BSON::Int64 ].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.database_field_name(name, relations, aliased_fields, aliased_associations) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the name of the provided field as it is stored in the database. Used in determining if the field is aliased or not. Recursively finds aliases for embedded documents and fields, delimited with period “.” character.

Note that this method returns the name of associations as they’re stored in the database, whereas the ‘relations` hash uses their in-code aliases. In order to check for membership in the relations hash, you would first have to look up the string returned from this method in the aliased_associations hash.

This method will not expand the alias of a belongs_to association that is not the last item. For example, if we had a School that has_many Students, and the field name passed was (from the Student’s perspective):

school._id

The alias for a belongs_to association is that association’s _id field. Therefore, expanding out this association would yield:

school_id._id

This is not the correct field name, because the intention here was not to get a property of the _id field. The intention was to get a property of the referenced document. Therefore, if a part of the name passed is a belongs_to association that is not the last part of the name, we won’t expand its alias, and return:

school._id

If the belongs_to association is the last part of the name, we will pass back the _id field.

Parameters:

  • name (String | Symbol)

    The name to get.

  • relations (Hash)

    The associations.

  • alaiased_fields (Hash)

    The aliased fields.

  • alaiased_associations (Hash)

    The aliased associations.

Returns:

  • (String)

    The name of the field as stored in the database.



407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 407

def database_field_name(name, relations, aliased_fields, aliased_associations)
  if Mongoid.broken_alias_handling
    return nil unless name
    normalized = name.to_s
    aliased_fields[normalized] || normalized
  else
    return nil unless name.present?
    key = name.to_s
    segment, remaining = key.split('.', 2)

    # Don't get the alias for the field when a belongs_to association
    # is not the last item. Therefore, get the alias when one of the
    # following is true:
    # 1. This is the last item, i.e. there is no remaining.
    # 2. It is not an association.
    # 3. It is not a belongs association
    if !remaining || !relations.key?(segment) || !relations[segment].is_a?(Association::Referenced::BelongsTo)
      segment = aliased_fields[segment]&.dup || segment
    end

    return segment unless remaining

    relation = relations[aliased_associations[segment] || segment]
    if relation
      k = relation.klass
      "#{segment}.#{database_field_name(remaining, k.relations, k.aliased_fields, k.aliased_associations)}"
    else
      "#{segment}.#{remaining}"
    end
  end
end

.option(option_name, &block) ⇒ Object

Stores the provided block to be run when the option name specified is defined on a field.

No assumptions are made about what functionality the handler might perform, so it will always be called if the ‘option_name` key is provided in the field definition – even if it is false or nil.

Examples:

Mongoid::Fields.option :required do |model, field, value|
  model.validates_presence_of field if value
end

Parameters:

  • option_name (Symbol)

    the option name to match against

  • block (Proc)

    the handler to execute when the option is provided.



292
293
294
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 292

def option(option_name, &block)
  options[option_name] = block
end

.optionsHash

Return a map of custom option names to their handlers.

Examples:

Mongoid::Fields.options
# => { :required => #<Proc:0x00000100976b38> }

Returns:

  • (Hash)

    the option map



303
304
305
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 303

def options
  @options ||= {}
end

.traverse_association_tree(key, fields, associations, aliased_associations) ⇒ Field

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Traverse down the association tree and search for the field for the given key. To do this, split the key by ‘.’ and for each part (meth) of the key:

  • If the meth is a field, yield the meth, field, and is_field as true.

  • If the meth is an association, update the klass to the association’s klass, and yield the meth, klass, and is_field as false.

The next iteration will use klass’s fields and associations to continue traversing the tree.

Parameters:

  • key (String)

    The key used to search the association tree.

  • fields (Hash)

    The fields to begin the search with.

  • associations (Hash)

    The associations to begin the search with.

  • aliased_associations (Hash)

    The alaised associations to begin the search with.

  • block (Proc)

    The block takes in three paramaters, the current meth, the field or the relation, and whether the second parameter is a field or not.

Returns:

  • (Field)

    The field found for the given key at the end of the search. This will return nil if the last thing found is an association or no field was found for the given key.



332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 332

def traverse_association_tree(key, fields, associations, aliased_associations)
  klass = nil
  field = nil
  key.split('.').each_with_index do |meth, i|
    fs = i == 0 ? fields : klass&.fields
    rs = i == 0 ? associations : klass&.relations
    as = i == 0 ? aliased_associations : klass&.aliased_associations

    # Associations can possibly have two "keys", their name and their alias.
    # The fields name is what is used to store it in the klass's relations
    # and field hashes, and the alias is what's used to store that field
    # in the database. The key inputted to this function is the aliased
    # key. We can convert them back to their names by looking in the
    # aliased_associations hash.
    aliased = meth
    if as && a = as.fetch(meth, nil)
      aliased = a.to_s
    end

    field = nil
    klass = nil
    if fs && f = fs[aliased]
      field = f
      yield(meth, f, true) if block_given?
    elsif rs && rel = rs[aliased]
      klass = rel.klass
      yield(meth, rel, false) if block_given?
    else
      yield(meth, nil, false) if block_given?
    end
  end
  field
end

Instance Method Details

#apply_default(name) ⇒ Object

Applies a single default value for the given name.

Examples:

Apply a single default.

model.apply_default("name")

Parameters:

  • name (String)

    The name of the field.



176
177
178
179
180
181
182
183
184
185
186
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 176

def apply_default(name)
  unless attributes.key?(name)
    if field = fields[name]
      default = field.eval_default(self)
      unless default.nil? || field.lazy?
        attribute_will_change!(name)
        attributes[name] = default
      end
    end
  end
end

#apply_defaultsObject

Apply all the defaults at once.

Examples:

Apply all the defaults.

model.apply_defaults


192
193
194
195
196
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 192

def apply_defaults
  pending_callbacks.delete(:apply_defaults)
  apply_pre_processed_defaults
  apply_post_processed_defaults
end

#apply_post_processed_defaultsArray<String>

Apply all default values to the document which are procs.

Examples:

Apply all the proc defaults.

model.apply_post_processed_defaults

Returns:

  • (Array<String>)

    The names of the proc defaults.



163
164
165
166
167
168
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 163

def apply_post_processed_defaults
  pending_callbacks.delete(:apply_post_processed_defaults)
  post_processed_defaults.each do |name|
    apply_default(name)
  end
end

#apply_pre_processed_defaultsArray<String>

Apply all default values to the document which are not procs.

Examples:

Apply all the non-proc defaults.

model.apply_pre_processed_defaults

Returns:

  • (Array<String>)

    The names of the non-proc defaults.



151
152
153
154
155
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 151

def apply_pre_processed_defaults
  pre_processed_defaults.each do |name|
    apply_default(name)
  end
end

#attribute_namesArray<String>

Returns an array of names for the attributes available on this object.

Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this method to automatically wrap params in JSON requests.

Examples:

Get the field names

document.attribute_names

Returns:

  • (Array<String>)

    The field names



207
208
209
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 207

def attribute_names
  self.class.attribute_names
end

#database_field_name(name) ⇒ String

Get the name of the provided field as it is stored in the database. Used in determining if the field is aliased or not.

Examples:

Get the database field name.

model.database_field_name(:authorization)

Parameters:

  • name (String | Symbol)

    The name to get.

Returns:

  • (String)

    The name of the field as it’s stored in the db.



220
221
222
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 220

def database_field_name(name)
  self.class.database_field_name(name)
end

#dot_dollar_field?(name) ⇒ true | false

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Does this field start with a dollar sign ($) or contain a dot/period (.)?

Parameters:

  • name (String)

    The field name.

Returns:

  • (true | false)

    If this field is dotted or dollared.



256
257
258
259
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 256

def dot_dollar_field?(name)
  n = aliased_fields[name] || name
  fields.key?(n) && (n.include?('.') || n.start_with?('$'))
end

#lazy_settable?(field, value) ⇒ true | false

Is the provided field a lazy evaluation?

Examples:

If the field is lazy settable.

doc.lazy_settable?(field, nil)

Parameters:

  • field (Field)

    The field.

  • value (Object)

    The current value.

Returns:

  • (true | false)

    If we set the field lazily.



233
234
235
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 233

def lazy_settable?(field, value)
  !frozen? && value.nil? && field.lazy?
end

#using_object_ids?true | false

Note:

Refactored from using delegate for class load performance.

Is the document using object ids?

Examples:

Is the document using object ids?

model.using_object_ids?

Returns:

  • (true | false)

    Using object ids.



245
246
247
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 245

def using_object_ids?
  self.class.using_object_ids?
end

#validate_writable_field_name!(name) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Validate whether or not the field starts with a dollar sign ($) or contains a dot/period (.).

Parameters:

  • name (String)

    The field name.

Raises:

  • (InvalidDotDollarAssignment)

    If contains dots or starts with a dollar.



269
270
271
272
273
# File 'build/mongoid-8.1/lib/mongoid/fields.rb', line 269

def validate_writable_field_name!(name)
  if dot_dollar_field?(name)
    raise Errors::InvalidDotDollarAssignment.new(self.class, name)
  end
end