class DataMapper::Associations::ManyToMany::Collection

Public Instance Methods

destroy() click to toggle source

Remove every Resource in the m:m Collection from the repository

This performs a deletion of each Resource in the Collection from the repository and clears the Collection.

@return [Boolean]

true if the resources were successfully destroyed

@api public

# File lib/dm-core/associations/many_to_many.rb, line 328
def destroy
  assert_source_saved 'The source must be saved before mass-deleting the collection'

  # make sure the records are loaded so they can be found when
  # the intermediaries are removed
  lazy_load

  unless intermediaries.all(via => self).destroy
    return false
  end

  super
end
destroy!() click to toggle source

Remove every Resource in the m:m Collection from the repository, bypassing validation

This performs a deletion of each Resource in the Collection from the repository and clears the Collection while skipping validation.

@return [Boolean]

true if the resources were successfully destroyed

@api public

# File lib/dm-core/associations/many_to_many.rb, line 352
def destroy!
  assert_source_saved 'The source must be saved before mass-deleting the collection'

  model      = self.model
  key        = model.key(repository_name)
  conditions = Query.target_conditions(self, key, key)

  unless intermediaries.all(via => self).destroy!
    return false
  end

  unless model.all(:repository => repository, :conditions => conditions).destroy!
    return false
  end

  each do |resource|
    resource.persistence_state = Resource::PersistenceState::Immutable.new(resource)
  end

  clear

  true
end
intermediaries() click to toggle source

Return the intermediaries linking the source to the targets

@return [Collection]

the intermediary collection

@api public

# File lib/dm-core/associations/many_to_many.rb, line 382
def intermediaries
  through = self.through
  source  = self.source

  @intermediaries ||= if through.loaded?(source)
    through.get_collection(source)
  else
    reset_intermediaries
  end
end

Protected Instance Methods

intermediary_for() click to toggle source

Map the resources in the collection to the intermediaries

@return [Hash]

the map of resources to their intermediaries

@api private

# File lib/dm-core/associations/many_to_many.rb, line 401
def intermediary_for
  @intermediary_for ||= {}
end
through() click to toggle source

@api private

# File lib/dm-core/associations/many_to_many.rb, line 406
def through
  relationship.through
end
via() click to toggle source

@api private

# File lib/dm-core/associations/many_to_many.rb, line 411
def via
  relationship.via
end

Private Instance Methods

_create(attributes, execute_hooks = true) click to toggle source

@api private

Calls superclass method DataMapper::Associations::OneToMany::Collection#_create
# File lib/dm-core/associations/many_to_many.rb, line 418
def _create(attributes, execute_hooks = true)
  via = self.via
  if via.respond_to?(:resource_for)
    resource = super
    if create_intermediary(execute_hooks, resource)
      resource
    end
  else
    if intermediary = create_intermediary(execute_hooks)
      super(attributes.merge(via.inverse => intermediary), execute_hooks)
    end
  end
end
_save(execute_hooks = true) click to toggle source

@api private

Calls superclass method DataMapper::Associations::OneToMany::Collection#_save
# File lib/dm-core/associations/many_to_many.rb, line 433
def _save(execute_hooks = true)
  via = self.via

  if @removed.any?
    # delete only intermediaries linked to the removed targets
    return false unless intermediaries.all(via => @removed).send(execute_hooks ? :destroy : :destroy!)

    # reset the intermediaries so that it reflects the current state of the datastore
    reset_intermediaries
  end

  loaded_entries = self.loaded_entries

  if via.respond_to?(:resource_for)
    super
    loaded_entries.all? { |resource| create_intermediary(execute_hooks, resource) }
  else
    if loaded_entries.any? && (intermediary = create_intermediary(execute_hooks))
      inverse = via.inverse
      loaded_entries.each { |resource| inverse.set(resource, intermediary) }
    end

    super
  end
end
create_intermediary(execute_hooks, resource = nil) click to toggle source

@api private

# File lib/dm-core/associations/many_to_many.rb, line 460
def create_intermediary(execute_hooks, resource = nil)
  intermediary_for = self.intermediary_for

  intermediary_resource = intermediary_for[resource]
  return intermediary_resource if intermediary_resource

  intermediaries = self.intermediaries
  method         = execute_hooks ? :save : :save!

  return unless intermediaries.send(method)

  attributes = {}
  attributes[via] = resource if resource

  intermediary = intermediaries.first_or_new(attributes)
  return unless intermediary.__send__(method)

  # map the resource, even if it is nil, to the intermediary
  intermediary_for[resource] = intermediary
end
inverse_set(*) click to toggle source

@api private

# File lib/dm-core/associations/many_to_many.rb, line 490
def inverse_set(*)
  # do nothing
end
reset_intermediaries() click to toggle source

@api private

# File lib/dm-core/associations/many_to_many.rb, line 482
def reset_intermediaries
  through = self.through
  source  = self.source

  through.set_collection(source, through.collection_for(source))
end