Why are acts-as-taggable-on tags lost during update?

374 Views Asked by At

I am using acts-as-taggable-on in a Ruby on Rails app to allow users to add tags to a list of their contacts (like a tagged address book). Adding/updating contacts with tags works perfectly for the user using standard RESTful paths contacts/new, contacts/[:id], contacts/:id/edit, etc.

I'm now trying to add functionality so the user can send an email to the contact requesting they confirm and complete their details. The email request includes a link to a page built on a different controller that shows a form (aka "the confirm form") with all the contact details, minus the tags (which are personal to the user).

The email link is of the form:

contact_confirmation/[:id]/edit?contact_id=[:contact_id]

Where [:id] is a token giving one-time access to the contact to update their details (this is like a pretty standard password reset).

The confirm form updates all the contact details correctly, but for some reason, the tags are lost. The params[] in both cases are the same, and the update method is the same.

Looking at the logs, they are identical up to the first COMMIT. Then the confirm form starts a new process (BEGIN) and deletes the tags:

(0.2ms)  BEGIN
CACHE ActsAsTaggableOn::Tag Load (0.0ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)  [["taggable_id", 9], ["taggable_type", "Contact"]]
CACHE ActsAsTaggableOn::Tag Load (0.0ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL)  [["taggable_id", 9], ["taggable_type", "Contact"]]
CACHE ActsAsTaggableOn::Tag Load (0.0ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."tagger_id" = $3 AND "taggings"."tagger_type" = $4 AND "taggings"."context" = $5  [["taggable_id", 9], ["taggable_type", "Contact"], ["tagger_id", 1], ["tagger_type", "User"], ["context", "tags"]]
ActsAsTaggableOn::Tagging Load (0.6ms)  SELECT "taggings".* FROM "taggings" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."tagger_type" = $3 AND "taggings"."tagger_id" = $4 AND "taggings"."tag_id" IN (5, 43, 44) AND "taggings"."context" = $5  [["taggable_id", 9], ["taggable_type", "Contact"], ["tagger_type", "User"], ["tagger_id", 1], ["context", "tags"]]
SQL (0.5ms)  DELETE FROM "taggings" WHERE "taggings"."id" = $1  [["id", 152]]
ActsAsTaggableOn::Tag Load (0.5ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
SQL (0.8ms)  UPDATE "tags" SET "taggings_count" = COALESCE("taggings_count", 0) - 1 WHERE "tags"."id" = $1  [["id", 5]]
ActsAsTaggableOn::Tag Load (1.3ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 5], ["LIMIT", 1]]
SQL (0.8ms)  DELETE FROM "taggings" WHERE "taggings"."id" = $1  [["id", 153]]
ActsAsTaggableOn::Tag Load (0.4ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 43], ["LIMIT", 1]]
SQL (0.5ms)  UPDATE "tags" SET "taggings_count" = COALESCE("taggings_count", 0) - 1 WHERE "tags"."id" = $1  [["id", 43]]
ActsAsTaggableOn::Tag Load (0.4ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 43], ["LIMIT", 1]]
ActsAsTaggableOn::Tagging Load (0.3ms)  SELECT "taggings".* FROM "taggings" WHERE "taggings"."tag_id" = $1  [["tag_id", 43]]
SQL (0.5ms)  DELETE FROM "tags" WHERE "tags"."id" = $1  [["id", 43]]
SQL (0.5ms)  DELETE FROM "taggings" WHERE "taggings"."id" = $1  [["id", 154]]
ActsAsTaggableOn::Tag Load (0.4ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 44], ["LIMIT", 1]]
SQL (0.9ms)  UPDATE "tags" SET "taggings_count" = COALESCE("taggings_count", 0) - 1 WHERE "tags"."id" = $1  [["id", 44]]
ActsAsTaggableOn::Tag Load (0.4ms)  SELECT  "tags".* FROM "tags" WHERE "tags"."id" = $1 LIMIT $2  [["id", 44], ["LIMIT", 1]]
ActsAsTaggableOn::Tagging Load (0.5ms)  SELECT "taggings".* FROM "taggings" WHERE "taggings"."tag_id" = $1  [["tag_id", 44]]
SQL (2.0ms)  DELETE FROM "tags" WHERE "tags"."id" = $1  [["id", 44]]
ActsAsTaggableOn::Tag Load (3.1ms)  SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."tagger_id" = $3 AND "taggings"."tagger_type" = $4 AND "taggings"."context" = $5  [["taggable_id", 9], ["taggable_type", "Contact"], ["tagger_id", 1], ["tagger_type", "User"], ["context", "tags"]]
(1.2ms)  COMMIT

Can anyone help me work out why this is happening? Thanks.

1

There are 1 best solutions below

0
On

Answered by: https://stackoverflow.com/a/25018540/6569994

I had to add the if tag_list_changed? condition to set_tag_owner on the contact model:

def set_tag_owner
  if tag_list_changed?
    set_owner_tag_list_on(account, :tags, tag_list)
    self.tag_list = nil
  end
end

I think in a normal form, the tags must be stripped and re-added each time.