123456789_123456789_123456789_123456789_123456789_

Module: Mongoid::Threaded

Relationships & Source Files
Namespace Children
Modules:
Defined in: lib/mongoid/threaded.rb,
lib/mongoid/threaded/lifecycle.rb

Overview

This module contains logic for easy access to objects that have a lifecycle on the current thread.

Constant Summary

Instance Attribute Summary

Instance Method Summary

Instance Attribute Details

#client_overrideString | Symbol (rw)

Get the global client override.

Examples:

Get the global client override.

Threaded.client_override

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 278

def client_override
  get(CLIENT_OVERRIDE_KEY)
end

#client_override=(name) ⇒ String | Symbol (rw)

::Set the global client override.

Examples:

::Set the global client override.

Threaded.client_override = :testing

Parameters:

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 290

def client_override=(name)
  set(CLIENT_OVERRIDE_KEY, name)
end

#database_overrideString | Symbol (rw)

Get the global database override.

Examples:

Get the global database override.

Threaded.database_override

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 135

def database_override
  get(DATABASE_OVERRIDE_KEY)
end

#database_override=(name) ⇒ String | Symbol (rw)

::Set the global database override.

Examples:

::Set the global database override.

Threaded.database_override = :testing

Parameters:

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 147

def database_override=(name)
  set(DATABASE_OVERRIDE_KEY, name)
end

#execute_callbacks=(flag) (rw)

Indicates whether document callbacks should be invoked by default for the current thread. Individual documents may further override the callback behavior, but this will be used for the default behavior.

Parameters:

  • flag (true | false)

    Whether or not document callbacks should be executed by default.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 538

def execute_callbacks=(flag)
  set(EXECUTE_CALLBACKS, flag)
end

#execute_callbacks?true | false (rw)

Queries whether document callbacks should be executed by default for the current thread.

Unless otherwise indicated (by #execute_callbacks=), this will return true.

Returns:

  • (true | false)

    Whether or not document callbacks should be executed by default.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 524

def execute_callbacks?
  if has?(EXECUTE_CALLBACKS)
    get(EXECUTE_CALLBACKS)
  else
    true
  end
end

Instance Method Details

#add_modified_document(session, document)

Store a reference to the document that was modified inside a transaction associated with the session.

Parameters:

  • session (Mongo::Session)

    Session in scope of which the document was modified.

  • document (Mongoid::Document)

    ::Mongoid document that was modified.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 499

def add_modified_document(session, document)
  return unless session&.in_transaction?

  modified_documents[session] << document
end

#autosaved?(document) ⇒ true | false

Is the document autosaved on the current thread?

Examples:

Is the document autosaved?

Threaded.autosaved?(doc)

Parameters:

  • document (Document)

    The document to check.

Returns:

  • (true | false)

    If the document is autosaved.

[ GitHub ]

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

def autosaved?(document)
  autosaves_for(document.class).include?(document._id)
end

#autosavesHash

Get all autosaves on the current thread.

Examples:

Get all autosaves.

Threaded.autosaves

Returns:

  • (Hash)

    The current autosaves.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 398

def autosaves
  get(AUTOSAVES_KEY) { {} }
end

#autosaves_for(klass) ⇒ Array

Get all autosaves on the current thread for the class.

Examples:

Get all autosaves.

Threaded.autosaves_for(Person)

Parameters:

  • klass (Class)

    The class to check.

Returns:

  • (Array)

    The current autosaves.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 420

def autosaves_for(klass)
  autosaves[klass] ||= []
end

#begin_autosave(document)

Begin autosaving a document on the current thread.

Examples:

Begin autosave.

Threaded.begin_autosave(doc)

Parameters:

  • document (Document)

    The document to autosave.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 193

def begin_autosave(document)
  autosaves_for(document.class).push(document._id)
end

#begin_execution(name) ⇒ true

Begin entry into a named thread local stack.

Examples:

Begin entry into the stack.

Threaded.begin_execution(:create)

Parameters:

  • name (String)

    The name of the stack

Returns:

  • (true)

    True.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 125

def begin_execution(name)
  stack(name).push(true)
end

#begin_touch_merged(document)

Mark that a document’s touch updates have been merged into an atomic insert on the current thread.

Examples:

Begin touch merged.

Threaded.begin_touch_merged(doc)

Parameters:

  • document (Document)

    The embedded document being inserted.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 214

def begin_touch_merged(document)
  touch_merged_for(document.class).push(document._id)
end

#begin_validate(document)

Begin validating a document on the current thread.

Examples:

Begin validation.

Threaded.begin_validate(doc)

Parameters:

  • document (Document)

    The document to validate.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 203

def begin_validate(document)
  validations_for(document.class).push(document._id)
end

#begin_without_default_scope(klass)

This method is for internal use only.

Begin suppressing default scopes for given model on the current thread.

Examples:

Begin without default scope stack.

Threaded.begin_without_default_scope(klass)

Parameters:

  • klass (Class)

    The model to suppress default scoping on.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 256

def begin_without_default_scope(klass)
  stack(:without_default_scope).push(klass)
end

#clear_modified_documents(session) ⇒ Set<Mongoid::Document>

Clears the set of modified documents for the given session, and return the content of the set before the clearance.

Parameters:

  • session (Mongo::Session)

    Session for which the modified documents set should be cleared.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 512

def clear_modified_documents(session)
  modified_documents.delete(session) || []
end

#clear_session(client: nil) ⇒ nil

Note:

For backward compatibility it is allowed to call this method without

Clear the cached session for this thread for a client.

specifying Mongoid#client parameter.

Parameters:

  • client (Mongo::Client | nil)

    The client to clear the session for.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 489

def clear_session(client: nil)
  sessions.delete(client)&.end_session
end

#current_scope(klass = nil) ⇒ Criteria

Get the current ::Mongoid scope.

Examples:

Get the scope.

Threaded.current_scope(klass)
Threaded.current_scope

Parameters:

  • klass (Klass) (defaults to: nil)

    The class type of the scope.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 303

def current_scope(klass = nil)
  current_scope = get(CURRENT_SCOPE_KEY)

  if klass && current_scope.respond_to?(:keys)
    current_scope[current_scope.keys.find { |k| k <= klass }]
  else
    current_scope
  end
end

#current_scope=(scope) ⇒ Criteria

::Set the current ::Mongoid scope.

Examples:

::Set the scope.

Threaded.current_scope = scope

Parameters:

  • scope (Criteria)

    The current scope.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 321

def current_scope=(scope)
  set(CURRENT_SCOPE_KEY, scope)
end

#delete(key)

Removes the named variable from local storage.

Parameters:

  • key (String | Symbol)

    the name of the variable to remove.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 104

def delete(key)
  storage.delete(key)
end

#executing?(name) ⇒ true

Are in the middle of executing the named stack

Examples:

Are we in the stack execution?

Threaded.executing?(:create)

Parameters:

  • name (Symbol)

    The name of the stack

Returns:

  • (true)

    If the stack is being executed.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 159

def executing?(name)
  !stack(name).empty?
end

#exit_autosave(document)

Exit autosaving a document on the current thread.

Examples:

Exit autosave.

Threaded.exit_autosave(doc)

Parameters:

  • document (Document)

    The document to autosave.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 224

def exit_autosave(document)
  autosaves_for(document.class).delete_one(document._id)
end

#exit_execution(name) ⇒ true

Exit from a named thread local stack.

Examples:

Exit from the stack.

Threaded.exit_execution(:create)

Parameters:

  • name (Symbol)

    The name of the stack

Returns:

  • (true)

    True.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 171

def exit_execution(name)
  stack(name).pop
end

#exit_touch_merged(document)

Clear the touch-merged flag for a document on the current thread.

Examples:

Exit touch merged.

Threaded.exit_touch_merged(doc)

Parameters:

  • document (Document)

    The document to clear.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 244

def exit_touch_merged(document)
  touch_merged_for(document.class).delete_one(document._id)
end

#exit_validate(document)

Exit validating a document on the current thread.

Examples:

Exit validation.

Threaded.exit_validate(doc)

Parameters:

  • document (Document)

    The document to validate.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 234

def exit_validate(document)
  validations_for(document.class).delete_one(document._id)
end

#exit_without_default_scope(klass)

This method is for internal use only.

Exit suppressing default scopes for given model on the current thread.

Examples:

Exit without default scope stack.

Threaded.exit_without_default_scope(klass)

Parameters:

  • klass (Class)

    The model to unsuppress default scoping on.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 268

def exit_without_default_scope(klass)
  stack(:without_default_scope).delete(klass)
end

#get(key, &default) ⇒ Object | nil

Queries the thread- or fiber-local variable with the given name. If a block is given, and the variable does not already exist, the return value of the block will be set as the value of the variable before returning it.

It is very important that applications (and especially ::Mongoid) use this method instead of Thread#[], since Thread#[] is actually for fiber-local variables, and ::Mongoid uses Fibers as an implementation detail in some callbacks. Putting thread-local state in a fiber-local store will result in the state being invisible when relevant callbacks are run in a different fiber.

Affected callbacks are cascading callbacks on embedded children.

Parameters:

  • key (String | Symbol)

    the name of the variable to query

  • default (Proc)

    an optional block that must return the default (initial) value of this variable.

Returns:

  • (Object | nil)

    the value of the queried variable, or nil if it is not set and no default was given.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 79

def get(key, &default)
  result = storage[key]

  if result.nil? && default
    result = yield
    set(key, result)
  end

  result
end

#get_session(client: nil) ⇒ Mongo::Session | nil

Note:

For backward compatibility it is allowed to call this method without

Get the cached session for this thread for a client.

specifying Mongoid#client parameter.

Parameters:

  • client (Mongo::Client | nil)

    The client to cache the session for.

Returns:

  • (Mongo::Session | nil)

    The session cached on this thread or nil.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 477

def get_session(client: nil)
  sessions[client]
end

#has?(key) ⇒ true | false

Queries the presence of a named variable in local storage.

Parameters:

  • key (String | Symbol)

    the name of the variable to query.

Returns:

  • (true | false)

    whether the given variable is present or not.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 113

def has?(key)
  storage.key?(key)
end

#modified_documentsHash<Mongo::Session, Set<Mongoid::Document>>

This method is for internal use only.

Returns the thread store of modified documents.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 557

def modified_documents
  get(MODIFIED_DOCUMENTS_KEY) { Hash.new { |h, k| h[k] = Set.new } }
end

#reset!

Resets the current thread- or fiber-local storage to its initial state. This is useful for making sure the state is clean when starting a new thread or fiber.

The value of Config.real_isolation_level is used to determine whether to reset the storage for the current thread or fiber.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 49

def reset!
  case Config.real_isolation_level
  when :thread
    Thread.current.thread_variable_set(STORAGE_KEY, nil)
  when :fiber
    Fiber[STORAGE_KEY] = nil
  else
    raise "Unknown isolation level: #{Config.real_isolation_level.inspect}"
  end
end

#sessionsHash<Integer, Set>

This method is for internal use only.

Returns the thread store of sessions.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 547

def sessions
  get(SESSIONS_KEY) { {}.compare_by_identity }
end

#set(key, value)

Sets a variable in local storage with the given name to the given value. See #get for a discussion of why this method is necessary, and why Thread#[]= should be avoided in cascading callbacks on embedded children.

Parameters:

  • key (String | Symbol)

    the name of the variable to set.

  • value (Object | nil)

    the value of the variable to set (or nil if you wish to unset the variable)

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 97

def set(key, value)
  storage[key] = value
end

#set_current_scope(scope, klass) ⇒ Criteria

::Set the current ::Mongoid scope. Safe for multi-model scope chaining.

Examples:

::Set the scope.

Threaded.current_scope(scope, klass)

Parameters:

  • scope (Criteria)

    The current scope.

  • klass (Class)

    The current model class.

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 334

def set_current_scope(scope, klass)
  if scope.nil?
    unset_current_scope(klass)
  else
    current_scope = get(CURRENT_SCOPE_KEY) { {} }
    current_scope[klass] = scope
  end
end

#set_session(session, client: nil)

Note:

For backward compatibility it is allowed to call this method without

Cache a session for this thread for a client.

specifying Mongoid#client parameter.

Parameters:

  • session (Mongo::Session)

    The session to save.

  • client (Mongo::Client | nil)

    The client to cache the session for.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 465

def set_session(session, client: nil)
  sessions[client] = session
end

#stack(name) ⇒ Array

Get the named stack.

Examples:

Get a stack by name

Threaded.stack(:create)

Parameters:

  • name (Symbol)

    The name of the stack

Returns:

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 183

def stack(name)
  get(STACK_KEYS[name]) { [] }
end

#storage (private)

Returns the current thread- or fiber-local storage as a ::Hash.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 577

def storage
  case Config.real_isolation_level
  when :thread
    storage_hash = Thread.current.thread_variable_get(STORAGE_KEY)

    unless storage_hash
      storage_hash = {}
      Thread.current.thread_variable_set(STORAGE_KEY, storage_hash)
    end

    storage_hash

  when :fiber
    Fiber[STORAGE_KEY] ||= {}

  else
    raise "Unknown isolation level: #{Config.real_isolation_level.inspect}"
  end
end

#touch_mergedHash

Get all touch-merged tracking on the current thread.

Examples:

Get all touch-merged.

Threaded.touch_merged

Returns:

  • (Hash)

    The current touch-merged tracking hash.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 442

def touch_merged
  get(TOUCH_MERGED_KEY) { {} }
end

#touch_merged?(document) ⇒ true | false

Is the document flagged as having had its touch updates merged into an atomic insert?

Examples:

Is the document touch-merged?

Threaded.touch_merged?(doc)

Parameters:

  • document (Document)

    The document to check.

Returns:

  • (true | false)

    If the document’s touch was merged.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 388

def touch_merged?(document)
  touch_merged_for(document.class).include?(document._id)
end

#touch_merged_for(klass) ⇒ Array

Get all touch-merged document IDs on the current thread for the class.

Examples:

Get all touch-merged.

Threaded.touch_merged_for(Sofa)

Parameters:

  • klass (Class)

    The class to check.

Returns:

  • (Array)

    The current touch-merged document IDs.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 454

def touch_merged_for(klass)
  touch_merged[klass] ||= []
end

#unset_current_scope(klass) (private)

Removes the given klass from the current scope, and tidies the current scope list.

Parameters:

  • klass (Class)

    the class to remove from the current scope.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 567

def unset_current_scope(klass)
  return unless has?(CURRENT_SCOPE_KEY)

  scope = get(CURRENT_SCOPE_KEY)
  scope.delete(klass)

  delete(CURRENT_SCOPE_KEY) if scope.empty?
end

#validated?(document) ⇒ true | false

Is the document validated on the current thread?

Examples:

Is the document validated?

Threaded.validated?(doc)

Parameters:

  • document (Document)

    The document to check.

Returns:

  • (true | false)

    If the document is validated.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 375

def validated?(document)
  validations_for(document.class).include?(document._id)
end

#validationsHash

Get all validations on the current thread.

Examples:

Get all validations.

Threaded.validations

Returns:

  • (Hash)

    The current validations.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 408

def validations
  get(VALIDATIONS_KEY) { {} }
end

#validations_for(klass) ⇒ Array

Get all validations on the current thread for the class.

Examples:

Get all validations.

Threaded.validations_for(Person)

Parameters:

  • klass (Class)

    The class to check.

Returns:

  • (Array)

    The current validations.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 432

def validations_for(klass)
  validations[klass] ||= []
end

#without_default_scope?(klass) ⇒ Boolean

This method is for internal use only.

Is the given klass’ default scope suppressed on the current thread?

Examples:

Is the given klass’ default scope suppressed?

Threaded.without_default_scope?(klass)

Parameters:

  • klass (Class)

    The model to check for default scope suppression.

[ GitHub ]

  
# File 'lib/mongoid/threaded.rb', line 351

def without_default_scope?(klass)
  stack(:without_default_scope).include?(klass)
end