Reputation: 166
I'm sure this has been answered hundreds of times, but I have searched and tried 100 things this morning so I am just going to ask the question. Feel free to just link me to another post...
I have 3 models: Notes, Tags, NoteTags (join)
Notes have many tags, tags have many notes; I'm trying to destroy a Note, the NoteTag link is being destroyed but the Tags remain.
Models:
class Note < ApplicationRecord
has_many :note_tags
has_many :tags, -> { uniq }, through: :note_tags, dependent: :destroy
end
class Tag < ApplicationRecord
has_many :note_tags
has_many :notes, through: :note_tags, dependent: :destroy
end
class NoteTag < ApplicationRecord
belongs_to :note
belongs_to :tag
end
So, obviously if the Tag still has a different note that has it, I don't want it to be deleted.. but if it's no longer featured in the note_tag table, it should be removed...
Is there any way of doing this?!
Thanks
Upvotes: 0
Views: 182
Reputation: 3005
You could destroy orphan tags after destroying the note.
def destroy
@note = Note.find_by(id: params[:id])
if @note
@note.destroy_with_tags
end
end
def destroy_with_tags
oldtag_ids = tag_ids
destroy
Tag.find(oldtag_ids).each do |tag|
tag.destroy if tag.notes == []
end
end
There may be other more efficient approach, in case the number of tags is big.
Second approach (currently not working)
Use the normal destroy and add a callback to destroy orphan tags. This option does not work, but might work with some changes I could not test.
class Note << ApplicationRecord
before_destroy :old_tags
after_destroy :destroy_orphan_tags
def old_tags
@oldtag_ids = tag_ids
end
def destroy_orphan_tags
#Destroy tags that were associated to this note, if there are no more notes
Tag.find(@oldtag_ids).joins(:note_tags).group('tags.id').having("count (*) = 0").destroy_all
end
end
Upvotes: 1