Class: Mongoid::Association::Referenced::HasMany::Targets::Enumerable

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/mongoid/association/referenced/has_many/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.

Since:

  • 7.0

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target, base = nil, association = nil) ⇒ 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



253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 253

def initialize(target, base = nil, association = nil)
  @_base = base
  @_association = association
  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 if 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)

Since:

  • 7.0



498
499
500
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 498

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.

Since:

  • 7.0



19
20
21
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

def _added
  @_added
end

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

The three main instance variables are collections of documents.



19
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

attr_accessor :_added, :_loaded, :_unloaded

#_loadedObject

The three main instance variables are collections of documents.

Since:

  • 7.0



19
20
21
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

def _loaded
  @_loaded
end

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

The three main instance variables are collections of documents.



19
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

attr_accessor :_added, :_loaded, :_unloaded

#_unloadedObject

The three main instance variables are collections of documents.

Since:

  • 7.0



19
20
21
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

def _unloaded
  @_unloaded
end

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

The three main instance variables are collections of documents.



19
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 19

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



63
64
65
66
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 63

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



33
34
35
36
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 33

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



49
50
51
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 49

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



358
359
360
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 358

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



472
473
474
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 472

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



84
85
86
87
88
89
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 84

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



101
102
103
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 101

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



115
116
117
118
119
120
121
122
123
124
125
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 115

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



140
141
142
143
144
145
146
147
148
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 140

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



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 175

def each
  unless block_given?
    return to_enum
  end
  if _loaded?
    _loaded.each_pair do |id, doc|
      document = _added.delete(doc._id) || doc
      set_base(document)
      yield(document)
    end
  else
    unloaded_documents.each do |doc|
      document = _added.delete(doc._id) || _loaded.delete(doc._id) || doc
      _loaded[document._id] = document
      set_base(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



208
209
210
211
212
213
214
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 208

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

#first(opts = {}) ⇒ Document

Note:

Automatically adding a sort on _id when no other sort is defined on the criteria has the potential to cause bad performance issues. If you experience unexpected poor performance when using #first or #last, use the option { id_sort: :none }. Be aware that #first/#last won't guarantee order in this case.

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

Parameters:

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

    The options for the query returning the first document.

Options Hash (opts):

  • :id_sort (:none)

    Don't apply a sort on _id.

Returns:

  • (Document)

    The first document found.

Since:

  • 2.1.0



235
236
237
238
239
240
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 235

def first(opts = {})
  _loaded.try(:values).try(:first) ||
      _added[(ul = _unloaded.try(:first, opts)).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



306
307
308
309
310
311
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 306

def in_memory
  docs = (_loaded.values + _added.values)
  docs.each do |doc|
    yield(doc) if block_given?
  end
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



277
278
279
280
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 277

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



291
292
293
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 291

def inspect
  entries.inspect
end

#last(opts = {}) ⇒ Document

Note:

Automatically adding a sort on _id when no other sort is defined on the criteria has the potential to cause bad performance issues. If you experience unexpected poor performance when using #first or #last, use the option { id_sort: :none }. Be aware that #first/#last won't guarantee order in this case.

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

Parameters:

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

    The options for the query returning the first document.

Options Hash (opts):

  • :id_sort (:none)

    Don't apply a sort on _id.

Returns:

  • (Document)

    The last document found.

Since:

  • 2.1.0



332
333
334
335
336
337
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 332

def last(opts = {})
  _added.values.try(:last) ||
      _loaded.try(:values).try(:last) ||
      _added[(ul = _unloaded.try(:last, opts)).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



370
371
372
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 370

def marshal_dump
  [_added, _loaded, _unloaded, @executed]
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



382
383
384
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 382

def marshal_load(data)
  @_added, @_loaded, @_unloaded, @executed = 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



394
395
396
397
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 394

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



408
409
410
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 408

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



424
425
426
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 424

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



437
438
439
440
441
442
443
444
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 437

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



458
459
460
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 458

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



486
487
488
# File 'lib/mongoid/association/referenced/has_many/enumerable.rb', line 486

def uniq
  entries.uniq
end