Class: Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy

Inherits:
Mongoid::Association::Referenced::HasMany::Proxy show all
Defined in:
lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb

Overview

This class defines the behavior for all associations that are a many-to-many between documents in different collections.

Instance Attribute Summary

Attributes inherited from Proxy

#_association, #_base, #_target

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Mongoid::Association::Referenced::HasMany::Proxy

#delete_all, #destroy_all, #each, #exists?, #find, #initialize

Methods inherited from Many

#blank?, #create, #create!, #find_or_create_by, #find_or_create_by!, #find_or_initialize_by, #nil?, #respond_to?, #scoped, #serializable_hash

Methods inherited from Proxy

apply_ordering, #extend_proxies, #init, #klass, #reset_unloaded, #substitutable

Methods included from Marshalable

#marshal_dump, #marshal_load

Constructor Details

This class inherits a constructor from Mongoid::Association::Referenced::HasMany::Proxy

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class Mongoid::Association::Referenced::HasMany::Proxy

Class Method Details

.eager_loader(association, docs) ⇒ Object

Get the Eager object for this type of association.

Examples:

Get the eager loader object

Parameters:

  • association (Association)

    The association object.

  • docs (Array<Document>)

    The array of documents.



273
274
275
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 273

def eager_loader(association, docs)
  Eager.new(association, docs)
end

.embedded?false

Returns true if the association is an embedded one. In this case always false.

Examples:

Is this association embedded?

Referenced::ManyToMany.embedded?

Returns:

  • (false)

    Always false.



284
285
286
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 284

def embedded?
  false
end

Instance Method Details

#<<(*args) ⇒ Array<Document> Also known as: push

Appends a document or array of documents to the association. Will set the parent and update the index in the process.

Examples:

Append a document.

person.posts << post

Push a document.

person.posts.push(post)

Concat with other documents.

person.posts.concat([ post_one, post_two ])

Parameters:

Returns:

  • (Array<Document>)

    The loaded docs.



27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 27

def <<(*args)
  docs = args.flatten
  return concat(docs) if docs.size > 1
  if doc = docs.first
    append(doc)
    _base.add_to_set(foreign_key => doc.public_send(_association.primary_key))
    if child_persistable?(doc)
      doc.save
    end
  end
  unsynced(_base, foreign_key) and self
end

#build(attributes = {}, type = nil) {|doc| ... } ⇒ Document Also known as: new

Build a new document from the attributes and append it to this association without saving.

Examples:

Build a new document on the association.

person.posts.build(:title => "A new post")

Parameters:

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

    The attributes of the new document.

  • type (Class) (defaults to: nil)

    The optional subclass to build.

Yields:

  • (doc)

Returns:



83
84
85
86
87
88
89
90
91
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 83

def build(attributes = {}, type = nil)
  doc = Factory.build(type || klass, attributes)
  _base.public_send(foreign_key).push(doc.public_send(_association.primary_key))
  append(doc)
  doc.apply_post_processed_defaults
  unsynced(doc, inverse_foreign_key)
  yield(doc) if block_given?
  doc
end

#concat(documents) ⇒ Array<Document>

Appends an array of documents to the association. Performs a batch insert of the documents instead of persisting one at a time.

Examples:

Concat with other documents.

person.posts.concat([ post_one, post_two ])

Parameters:

  • documents (Array<Document>)

    The docs to add.

Returns:



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 51

def concat(documents)
  ids, docs, inserts = {}, [], []
  documents.each do |doc|
    next unless doc
    append(doc)
    if persistable? || _creating?
      ids[doc.public_send(_association.primary_key)] = true
      save_or_delay(doc, docs, inserts)
    else
      existing = _base.public_send(foreign_key)
      unless existing.include?(doc.public_send(_association.primary_key))
        existing.push(doc.public_send(_association.primary_key)) and unsynced(_base, foreign_key)
      end
    end
  end
  if persistable? || _creating?
    _base.push(foreign_key => ids.keys)
  end
  persist_delayed(docs, inserts)
  self
end

#delete(document) ⇒ Document

Delete the document from the association. This will set the foreign key on the document to nil. If the dependent options on the association are :delete_all or :destroy the appropriate removal will occur.

Examples:

Delete the document.

person.posts.delete(post)

Parameters:

  • document (Document)

    The document to remove.

Returns:



105
106
107
108
109
110
111
112
113
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 105

def delete(document)
  doc = super
  if doc && persistable?
    _base.pull(foreign_key => doc.public_send(_association.primary_key))
    _target._unloaded = criteria
    unsynced(_base, foreign_key)
  end
  doc
end

#nullify(replacement = []) ⇒ Object Also known as: nullify_all, clear, purge

Removes all associations between the base document and the target documents by deleting the foreign keys and the references, orphaning the target documents in the process.

Examples:

Nullify the association.

person.preferences.nullify

Parameters:

  • replacement (Array<Document>) (defaults to: [])

    The replacement documents.



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 123

def nullify(replacement = [])
  _target.each do |doc|
    execute_callback :before_remove, doc
  end
  unless _association.forced_nil_inverse?
    if field = _association.options[:inverse_primary_key]
      ipk = _base.public_send(field)
    else
      ipk = _base._id
    end
    if replacement
      objects_to_clear = _base.public_send(foreign_key) - replacement.collect do |object|
        object.public_send(_association.primary_key)
      end
      criteria(objects_to_clear).pull(inverse_foreign_key => ipk)
    else
      criteria.pull(inverse_foreign_key => ipk)
    end
  end
  if persistable?
    _base.set(foreign_key => _base.public_send(foreign_key).clear)
  end
  after_remove_error = nil
  many_to_many = _target.clear do |doc|
    unbind_one(doc)
    unless _association.forced_nil_inverse?
      doc.changed_attributes.delete(inverse_foreign_key)
    end
    begin
      execute_callback :after_remove, doc
    rescue => e
      after_remove_error = e
    end
  end
  raise after_remove_error if after_remove_error
  many_to_many
end

#substitute(replacement) ⇒ Many

Substitutes the supplied target documents for the existing documents in the association. If the new target is nil, perform the necessary deletion.

person.preferences.substitute([ new_post ])

Examples:

Replace the association.

Parameters:

  • replacement (Array<Document>)

    The replacement target.

Returns:

  • (Many)

    The association.



175
176
177
178
179
180
181
182
183
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 175

def substitute(replacement)
  purge(replacement)
  unless replacement.blank?
    push(replacement.compact.uniq)
  else
    reset_unloaded
  end
  self
end

#unscopedCriteria

Get a criteria for the documents without the default scoping applied.

Examples:

Get the unscoped criteria.

person.preferences.unscoped

Returns:



192
193
194
# File 'lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb', line 192

def unscoped
  klass.unscoped.any_in(_id: _base.public_send(foreign_key))
end