Class: Mongoid::Relations::Targets::Enumerable

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/mongoid/relations/targets/enumerable.rb

Overview

This class is the wrapper for all relational associations that have a target that can be a criteria or array of _loaded documents. This handles both cases or a combination of the two.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target) ⇒ Enumerable

Initialize the new enumerable either with a criteria or an array.

Examples:

Initialize the enumerable with a criteria.

Enumberable.new(Post.where(:person_id => id))

Initialize the enumerable with an array.

Enumerable.new([ post ])

Parameters:

Since:

  • 2.1.0



238
239
240
241
242
243
244
245
246
247
248
# File 'lib/mongoid/relations/targets/enumerable.rb', line 238

def initialize(target)
  if target.is_a?(Criteria)
    @_added, @executed, @_loaded, @_unloaded = {}, false, {}, target
  else
    @_added, @executed = {}, true
    @_loaded = target.inject({}) do |_target, doc|
      _target[doc._id] = doc
      _target
    end
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object (private)



463
464
465
# File 'lib/mongoid/relations/targets/enumerable.rb', line 463

def method_missing(name, *args, &block)
  entries.send(name, *args, &block)
end

Instance Attribute Details

#_addedObject

The three main instance variables are collections of documents.



17
18
19
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

def _added
  @_added
end

#_added Documents that have been appended.(Documentsthathavebeenappended.) ⇒ Object

The three main instance variables are collections of documents.



17
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

attr_accessor :_added, :_loaded, :_unloaded

#_loadedObject

The three main instance variables are collections of documents.



17
18
19
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

def _loaded
  @_loaded
end

#_loaded Persisted documents that have been _loaded.(Persisteddocumentsthathavebeen_loaded.) ⇒ Object

The three main instance variables are collections of documents.



17
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

attr_accessor :_added, :_loaded, :_unloaded

#_unloadedObject

The three main instance variables are collections of documents.



17
18
19
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

def _unloaded
  @_unloaded
end

#_unloaded A criteria representing persisted docs.(Acriteriarepresentingpersisteddocs.) ⇒ Object

The three main instance variables are collections of documents.



17
# File 'lib/mongoid/relations/targets/enumerable.rb', line 17

attr_accessor :_added, :_loaded, :_unloaded

Instance Method Details

#<<(document) ⇒ Document Also known as: push

Append a document to the enumerable.

Examples:

Append the document.

enumerable << document

Parameters:

  • document (Document)

    The document to append.

Returns:

Since:

  • 2.1.0



61
62
63
64
# File 'lib/mongoid/relations/targets/enumerable.rb', line 61

def <<(document)
  _added[document._id] = document
  self
end

#==(other) ⇒ true, false

Check if the enumerable is equal to the other object.

Examples:

Check equality.

enumerable == []

Parameters:

Returns:

  • (true, false)

    If the objects are equal.

Since:

  • 2.1.0



31
32
33
34
# File 'lib/mongoid/relations/targets/enumerable.rb', line 31

def ==(other)
  return false unless other.respond_to?(:entries)
  entries == other.entries
end

#===(other) ⇒ true, false

Check equality of the enumerable against the provided object for case statements.

Examples:

Check case equality.

enumerable === Array

Parameters:

  • other (Object)

    The object to check.

Returns:

  • (true, false)

    If the objects are equal in a case.

Since:

  • 3.1.4



47
48
49
# File 'lib/mongoid/relations/targets/enumerable.rb', line 47

def ===(other)
  other.class == Class ? (Array == other || Enumerable == other) : self == other
end

#_loaded?true, false

Has the enumerable been _loaded? This will be true if the criteria has been executed or we manually load the entire thing.

Examples:

Is the enumerable _loaded?

enumerable._loaded?

Returns:

  • (true, false)

    If the enumerable has been _loaded.

Since:

  • 2.1.0



330
331
332
# File 'lib/mongoid/relations/targets/enumerable.rb', line 330

def _loaded?
  !!@executed
end

#as_json(options = {}) ⇒ Hash

Send #as_json to the entries, without encoding.

Examples:

Get the enumerable as json.

enumerable.as_json

Parameters:

  • options (Hash) (defaults to: {})

    Optional parameters.

Returns:

  • (Hash)

    The entries all _loaded as a hash.

Since:

  • 2.2.0



443
444
445
# File 'lib/mongoid/relations/targets/enumerable.rb', line 443

def as_json(options = {})
  entries.as_json(options)
end

#clearArray<Document>

Clears out all the documents in this enumerable. If passed a block it will yield to each document that is in memory.

Examples:

Clear out the enumerable.

enumerable.clear

Clear out the enumerable with a block.

enumerable.clear do |doc|
  doc.unbind
end

Returns:

  • (Array<Document>)

    The cleared out _added docs.

Since:

  • 2.1.0



81
82
83
84
85
86
# File 'lib/mongoid/relations/targets/enumerable.rb', line 81

def clear
  if block_given?
    in_memory { |doc| yield(doc) }
  end
  _loaded.clear and _added.clear
end

#cloneArray<Document>

Note:

This loads all documents into memory.

Clones each document in the enumerable.

Examples:

Clone the enumerable.

enumerable.clone

Returns:

  • (Array<Document>)

    An array clone of the enumerable.

Since:

  • 2.1.6



98
99
100
# File 'lib/mongoid/relations/targets/enumerable.rb', line 98

def clone
  collect { |doc| doc.clone }
end

#delete(document) {|doc| ... } ⇒ Document

Delete the supplied document from the enumerable.

Examples:

Delete the document.

enumerable.delete(document)

Parameters:

  • document (Document)

    The document to delete.

Yields:

  • (doc)

Returns:

Since:

  • 2.1.0



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/mongoid/relations/targets/enumerable.rb', line 112

def delete(document)
  doc = (_loaded.delete(document._id) || _added.delete(document._id))
  unless doc
    if _unloaded && _unloaded.where(_id: document._id).exists?
      yield(document) if block_given?
      return document
    end
  end
  yield(doc) if block_given?
  doc
end

#delete_if(&block) ⇒ Array<Document>

Note:

This operation loads all documents from the database.

Deletes every document in the enumerable for where the block returns true.

Examples:

Delete all matching documents.

enumerable.delete_if do |doc|
  dod._id == _id
end

Returns:

  • (Array<Document>)

    The remaining docs.

Since:

  • 2.1.0



137
138
139
140
141
142
143
144
145
# File 'lib/mongoid/relations/targets/enumerable.rb', line 137

def delete_if(&block)
  load_all!
  deleted = in_memory.select(&block)
  deleted.each do |doc|
    _loaded.delete(doc._id)
    _added.delete(doc._id)
  end
  self
end

#eachtrue

Iterating over this enumerable has to handle a few different scenarios.

If the enumerable has its criteria _loaded into memory then it yields to all the _loaded docs and all the _added docs.

If the enumerable has not _loaded the criteria then it iterates over the cursor while loading the documents and then iterates over the _added docs.

If no block is passed then it returns an enumerator containing all docs.

Examples:

Iterate over the enumerable.

enumerable.each do |doc|
  puts doc
end

return an enumerator containing all the docs


a = enumerable.each

Returns:

  • (true)

    That the enumerable is now _loaded.

Since:

  • 2.1.0



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/mongoid/relations/targets/enumerable.rb', line 172

def each
  unless block_given?
    return to_enum
  end
  if _loaded?
    _loaded.each_pair do |id, doc|
      document = _added.delete(doc._id) || doc
      yield(document)
    end
  else
    unloaded_documents.each do |doc|
      document = _added.delete(doc._id) || _loaded.delete(doc._id) || doc
      _loaded[document._id] = document
      yield(document)
    end
  end
  _added.each_pair do |id, doc|
    yield(doc)
  end
  @executed = true
end

#empty?true, false

Is the enumerable empty? Will determine if the count is zero based on whether or not it is _loaded.

Examples:

Is the enumerable empty?

enumerable.empty?

Returns:

  • (true, false)

    If the enumerable is empty.

Since:

  • 2.1.0



203
204
205
206
207
208
209
# File 'lib/mongoid/relations/targets/enumerable.rb', line 203

def empty?
  if _loaded?
    in_memory.count == 0
  else
    _unloaded.count + _added.count == 0
  end
end

#firstDocument

Get the first document in the enumerable. Will check the persisted documents first. Does not load the entire enumerable.

Examples:

Get the first document.

enumerable.first

Returns:

  • (Document)

    The first document found.

Since:

  • 2.1.0



220
221
222
223
224
225
# File 'lib/mongoid/relations/targets/enumerable.rb', line 220

def first
  _loaded.try(:values).try(:first) ||
    _added[(ul = _unloaded.try(:first)).try(:id)] ||
    ul ||
    _added.values.try(:first)
end

#in_memoryArray<Document>

Note:

When passed a block it yields to each document.

Return all the documents in the enumerable that have been _loaded or _added.

Examples:

Get the in memory docs.

enumerable.in_memory

Returns:

  • (Array<Document>)

    The in memory docs.

Since:

  • 2.1.0



289
290
291
292
293
# File 'lib/mongoid/relations/targets/enumerable.rb', line 289

def in_memory
  docs = (_loaded.values + _added.values)
  docs.each { |doc| yield(doc) } if block_given?
  docs
end

#include?(doc) ⇒ true, false

Does the target include the provided document?

Examples:

Does the target include the document?

enumerable.include?(document)

Parameters:

  • doc (Document)

    The document to check.

Returns:

  • (true, false)

    If the document is in the target.

Since:

  • 3.0.0



260
261
262
263
# File 'lib/mongoid/relations/targets/enumerable.rb', line 260

def include?(doc)
  return super unless _unloaded
  _unloaded.where(_id: doc._id).exists? || _added.has_key?(doc._id)
end

#inspectString

Inspection will just inspect the entries for nice array-style printing.

Examples:

Inspect the enumerable.

enumerable.inspect

Returns:

  • (String)

    The inspected enum.

Since:

  • 2.1.0



274
275
276
# File 'lib/mongoid/relations/targets/enumerable.rb', line 274

def inspect
  entries.inspect
end

#lastDocument

Get the last document in the enumerable. Will check the new documents first. Does not load the entire enumerable.

Examples:

Get the last document.

enumerable.last

Returns:

  • (Document)

    The last document found.

Since:

  • 2.1.0



304
305
306
307
308
309
# File 'lib/mongoid/relations/targets/enumerable.rb', line 304

def last
  _added.values.try(:last) ||
    _loaded.try(:values).try(:last) ||
    _added[(ul = _unloaded.try(:last)).try(:id)] ||
    ul
end

#marshal_dumpArray<Object>

Provides the data needed to Marshal.dump an enumerable proxy.

Examples:

Dump the proxy.

Marshal.dump(proxy)

Returns:

  • (Array<Object>)

    The dumped data.

Since:

  • 3.0.15



342
343
344
# File 'lib/mongoid/relations/targets/enumerable.rb', line 342

def marshal_dump
  [ _added, _loaded, _unloaded ]
end

#marshal_load(data) ⇒ Array<Object>

Loads the data needed to Marshal.load an enumerable proxy.

Examples:

Load the proxy.

Marshal.load(proxy)

Returns:

  • (Array<Object>)

    The dumped data.

Since:

  • 3.0.15



354
355
356
# File 'lib/mongoid/relations/targets/enumerable.rb', line 354

def marshal_load(data)
  @_added, @_loaded, @_unloaded = data
end

#resetfalse

Reset the enumerable back to its persisted state.

Examples:

Reset the enumerable.

enumerable.reset

Returns:

  • (false)

    Always false.

Since:

  • 2.1.0



366
367
368
369
# File 'lib/mongoid/relations/targets/enumerable.rb', line 366

def reset
  _loaded.clear and _added.clear
  @executed = false
end

#reset_unloaded(criteria) ⇒ Object

Resets the underlying unloaded criteria object with a new one. Used my HABTM relations to keep the underlying array in sync.

Examples:

Reset the unloaded documents.

enumerable.reset_unloaded(criteria)

Parameters:

  • criteria (Criteria)

    The criteria to replace with.

Since:

  • 3.0.14



380
381
382
# File 'lib/mongoid/relations/targets/enumerable.rb', line 380

def reset_unloaded(criteria)
  @_unloaded = criteria if _unloaded.is_a?(Criteria)
end

#respond_to?(name, include_private = false) ⇒ true, false

Does this enumerable respond to the provided method?

Examples:

Does the enumerable respond to the method?

enumerable.respond_to?(:sum)

Parameters:

  • name (String, Symbol)

    The name of the method.

  • include_private (true, false) (defaults to: false)

    Whether to include private methods.

Returns:

  • (true, false)

    Whether the enumerable responds.

Since:

  • 2.1.0



396
397
398
# File 'lib/mongoid/relations/targets/enumerable.rb', line 396

def respond_to?(name, include_private = false)
  [].respond_to?(name, include_private) || super
end

#sizeInteger Also known as: length

Gets the total size of this enumerable. This is a combination of all the persisted and unpersisted documents.

Examples:

Get the size.

enumerable.size

Returns:

  • (Integer)

    The size of the enumerable.

Since:

  • 2.1.0



409
410
411
412
413
414
415
416
# File 'lib/mongoid/relations/targets/enumerable.rb', line 409

def size
  count = (_unloaded ? _unloaded.count : _loaded.count)
  if count.zero?
    count + _added.count
  else
    count + _added.values.count{ |d| d.new_record? }
  end
end

#to_json(options = {}) ⇒ String

Send #to_json to the entries.

Examples:

Get the enumerable as json.

enumerable.to_json

Parameters:

  • options (Hash) (defaults to: {})

    Optional parameters.

Returns:

  • (String)

    The entries all _loaded as a string.

Since:

  • 2.2.0



429
430
431
# File 'lib/mongoid/relations/targets/enumerable.rb', line 429

def to_json(options = {})
  entries.to_json(options)
end

#uniqArray<Document>

Note:

This operation loads all documents from the database.

Return all the unique documents in the enumerable.

Examples:

Get all the unique documents.

enumerable.uniq

Returns:

  • (Array<Document>)

    The unique documents.

Since:

  • 2.1.0



457
458
459
# File 'lib/mongoid/relations/targets/enumerable.rb', line 457

def uniq
  entries.uniq
end