lib/mongoid/relations/referenced/many_to_many.rb in mongoid-2.0.0.rc.4 vs lib/mongoid/relations/referenced/many_to_many.rb in mongoid-2.0.0.rc.5
- old
+ new
@@ -3,59 +3,24 @@
module Relations #:nodoc:
module Referenced #:nodoc:
# This class defines the behaviour for all relations that are a
# many-to-many between documents in different collections.
- class ManyToMany < Relations::Many
+ class ManyToMany < Referenced::Many
- # Binds the base object to the inverse of the relation. This is so we
- # are referenced to the actual objects themselves and dont hit the
- # database twice when setting the relations up.
- #
- # This is called after first creating the relation, or if a new object
- # is set on the relation.
- #
- # @example Bind the relation.
- # person.preferences.bind
- #
- # @param [ Hash ] options The options to bind with.
- #
- # @option options [ true, false ] :building Are we in build mode?
- # @option options [ true, false ] :continue Continue binding the
- # inverse?
- #
- # @since 2.0.0.rc.1
- def bind(options = {})
- loaded and binding.bind(options)
- target.map(&:save) if base.persisted? && !options[:building]
- end
-
- # Clear the relation. Will delete the documents from the db if they are
- # already persisted.
- #
- # @example Clear the relation.
- # person.preferences.clear
- #
- # @return [ Many ] The relation emptied.
- def clear
- tap do |relation|
- relation.unbind(default_options)
- target.clear
- end
- end
-
# Delete a single document from the relation.
#
# @example Delete a document.
# person.preferences.delete(preference)
#
# @param [ Document ] document The document to delete.
#
# @since 2.0.0.rc.1
def delete(document, options = {})
- target.delete(document)
- binding.unbind_one(document, options)
+ target.delete(document).tap do |doc|
+ binding.unbind_one(doc, default_options.merge!(options)) if doc
+ end
end
# Deletes all related documents from the database given the supplied
# conditions.
#
@@ -124,33 +89,20 @@
"_id" => { "$in" => base.send(metadata.foreign_key) }
)
klass.find(arg, :conditions => selector)
end
- # Instantiate a new references_many relation. Will set the foreign key
- # and the base on the inverse object.
- #
- # @example Create the new relation.
- # Referenced::ManyToMany.new(base, target, metadata)
- #
- # @param [ Document ] base The document this relation hangs off of.
- # @param [ Array<Document> ] target The target of the relation.
- # @param [ Metadata ] metadata The relation's metadata.
- def initialize(base, target, metadata)
- init(base, target, metadata)
- end
-
# 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.
#
# @example Nullify the relation.
# person.preferences.nullify
#
# @since 2.0.0.rc.1
def nullify
- loaded and target.each do |doc|
+ load! and target.each do |doc|
base.send(metadata.foreign_key).delete(doc.id)
dereference(doc)
end
target.clear
end
@@ -164,11 +116,11 @@
# person.posts.substitute(new_name)
#
# @param [ Array<Document> ] target The replacement target.
# @param [ Hash ] options The options to bind with.
#
- # @option options [ true, false ] :building Are we in build mode?
+ # @option options [ true, false ] :binding Are we in build mode?
# @option options [ true, false ] :continue Continue binding the
# inverse?
#
# @return [ Many ] The relation.
#
@@ -193,11 +145,11 @@
# @example Unbind the target.
# person.posts.unbind
#
# @param [ Hash ] options The options to bind with.
#
- # @option options [ true, false ] :building Are we in build mode?
+ # @option options [ true, false ] :binding Are we in build mode?
# @option options [ true, false ] :continue Continue binding the
# inverse?
#
# @since 2.0.0.rc.1
def unbind(options = {})
@@ -206,25 +158,10 @@
[]
end
private
- # Appends the document to the target array, updating the index on the
- # document at the same time.
- #
- # @example Append the document to the relation.
- # relation.append(document)
- #
- # @param [ Document ] document The document to append to the target.
- #
- # @since 2.0.0.rc.1
- def append(document, options = {})
- loaded and target.push(document)
- characterize_one(document)
- binding.bind_one(document, options)
- end
-
# Instantiate the binding associated with this relation.
#
# @example Get the binding.
# relation.binding([ address ])
#
@@ -243,11 +180,11 @@
# @example Get a criteria for the relation.
# relation.criteria
#
# @return [ Criteria ] A new criteria.
def criteria
- metadata.klass.criteria(false)
+ metadata.klass.any_in(metadata.inverse_foreign_key => [ base.id ])
end
# Dereferences the supplied document from the base of the relation.
#
# @example Dereference the document.
@@ -256,24 +193,9 @@
# @param [ Document ] document The document to dereference.
def dereference(document)
document.send(metadata.inverse_foreign_key).delete(base.id)
document.send(metadata.inverse(document)).target.delete(base)
document.save
- end
-
- # Will load the target into an array if the target had not already been
- # loaded.
- #
- # @example Load the relation into memory.
- # relation.loaded
- #
- # @return [ ManyToMany ] The relation.
- #
- # @since 2.0.0.rc.1
- def loaded
- tap do |relation|
- relation.target = target.entries if target.is_a?(Mongoid::Criteria)
- end
end
class << self
# Return the builder that is responsible for generating the documents