Skip to content

Instantly share code, notes, and snippets.

@paddyinpdx
Created March 30, 2011 22:17
Show Gist options
  • Save paddyinpdx/895428 to your computer and use it in GitHub Desktop.
Save paddyinpdx/895428 to your computer and use it in GitHub Desktop.
Mongoid 2.0 Workaround Methods for Update/Delete actions when using references_and_referenced_in_many
# tag.rb
class Tag
include Mongoid::Document
# Fields
field :title
# Associations
references_and_referenced_in_many :related, :class_name => "Tag"
before_save :flatten_related_tags # Needed for cases where related_ids == [[]]
before_destroy :delete_from_related_tags
before_destroy :delete_from_tagged_content
private
def delete_from_tagged_content
[Article,Pdf,Link].each do |model|
model.any_in(:tag_id => [self.id]).each do |item|
item.tag_id.delete(self.id)
item.save
end
end
end
def delete_from_related_tags
Tag.any_in(:related_ids => [self.id]).each do |_tag|
_tag.related.delete(self)
_tag.save
end
end
def flatten_related_tags
if defined?(self.related_ids)
self.related_ids.delete(self.id)
self.related_ids.flatten!
self.related_ids.uniq!
end
end
end
# tags_controller.rb
#
# Work around for fact that with Mongoid you cannot just use tag ids when setting relations. You have to work
# with the actual tag object. So I can't just pass params[:tag][:related_ids] to update the @tag.related_ids property.
# I have to convert the related_ids to related tags and update @tag.related.
def updateRelatedTags(current_tag, params_related_ids)
# First compare the existing related ids with the ones passed as a param. If a currently stored related_id is
# missing from the params, it has been deleted as a related tag. So *that* tag needs to have *this* tag's relation
# deleted as well.
deleted_related_tags = (current_tag.related_ids || []) - (params_related_ids || [])
if deleted_related_tags.any?
deleted_related_tags.each do |related_tag_id|
related_tag = Tag.criteria.for_ids(related_tag_id).first
if !related_tag.nil?
related_tag.related.delete(current_tag)
related_tag.save
end
end
end
# Now update this tag's related tags using its related property, not its related_ids property. If you use the former
# the tag being related will not store a relation to this tag.
if !params_related_ids.nil? && params_related_ids.any?
params_related_ids.each do |related_tag_id|
related_tag = Tag.criteria.for_ids(related_tag_id).first
if !related_tag.nil?
# This won't work if you try tag.related_ids.push(related_tag_id)
current_tag.related.push(related_tag)
end
end
else
# No related ids were passed in, so there are no longer any relations
current_tag.related = []
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment