FIX: ensures successive tags can be renamed (#12818)

FIX: ensures successive tags can be renamed (#12818)

Original bug report: Rename tag not working as expected - bug - Discourse Meta

This bug was caused by the use of oneWay which can be very dangerous in this case, from the documentation:

computed.oneWay only provides an aliased get. The set will not mutate the upstream property, rather causes the current property to become the value set. This causes the downstream property to permanently diverge from the upstream property.

diff --git a/app/assets/javascripts/discourse/app/controllers/rename-tag.js b/app/assets/javascripts/discourse/app/controllers/rename-tag.js
index 04dc73c..1c5f1d6 100644
--- a/app/assets/javascripts/discourse/app/controllers/rename-tag.js
+++ b/app/assets/javascripts/discourse/app/controllers/rename-tag.js
@@ -1,37 +1,33 @@
+import { action } from "@ember/object";
 import BufferedContent from "discourse/mixins/buffered-content";
 import Controller from "@ember/controller";
 import ModalFunctionality from "discourse/mixins/modal-functionality";
 import discourseComputed from "discourse-common/utils/decorators";
 import { extractError } from "discourse/lib/ajax-error";
-import { oneWay } from "@ember/object/computed";
 
 export default Controller.extend(ModalFunctionality, BufferedContent, {
-  tagId: oneWay("model.id"),
+  newTag: null,
 
-  @discourseComputed("tagId", "model.id")
-  renameDisabled(inputTagName, currentTagName) {
+  @discourseComputed("newTag", "model.id")
+  renameDisabled(newTag, currentTag) {
     const filterRegexp = new RegExp(this.site.tags_filter_regexp, "g");
-    const newTagName = inputTagName
-      ? inputTagName.replace(filterRegexp, "").trim()
-      : "";
-
-    return newTagName.length === 0 || newTagName === currentTagName;
+    newTag = newTag ? newTag.replace(filterRegexp, "").trim() : "";
+    return newTag.length === 0 || newTag === currentTag;
   },
 
-  actions: {
-    performRename() {
-      this.model
-        .update({ id: this.get("tagId") })
-        .then((result) => {
-          this.send("closeModal");
+  @action
+  performRename() {
+    this.model
+      .update({ id: this.newTag })
+      .then((result) => {
+        this.send("closeModal");
 
-          if (result.responseJson.tag) {
-            this.transitionToRoute("tag.show", result.responseJson.tag.id);
-          } else {
-            this.flash(extractError(result.responseJson.errors[0]), "error");
-          }
-        })
-        .catch((error) => this.flash(extractError(error), "error"));
-    },
+        if (result.responseJson.tag) {
+          this.transitionToRoute("tag.show", result.responseJson.tag.id);
+        } else {
+          this.flash(extractError(result.responseJson.errors[0]), "error");
+        }
+      })
+      .catch((error) => this.flash(extractError(error), "error"));
   },
 });
diff --git a/app/assets/javascripts/discourse/app/templates/modal/rename-tag.hbs b/app/assets/javascripts/discourse/app/templates/modal/rename-tag.hbs
index ed4b9af..0ce71cb 100644
--- a/app/assets/javascripts/discourse/app/templates/modal/rename-tag.hbs
+++ b/app/assets/javascripts/discourse/app/templates/modal/rename-tag.hbs
@@ -3,13 +3,19 @@
     {{i18n "tagging.rename_instructions"}}
   </label>
   <div class="controls">
-    {{input value=tagId maxlength=siteSettings.max_tag_length}}
+    {{input
+      value=(readonly model.id)
+      maxlength=siteSettings.max_tag_length
+      input=(action (mut newTag) value="target.value")
+    }}
   </div>
 {{/d-modal-body}}
 
 <div class="modal-footer">
-  {{d-button class="btn-primary"
-             action=(action "performRename")
-             label="tagging.rename_tag"
-             disabled=renameDisabled}}
+  {{d-button
+    class="btn-primary"
+    action=(action "performRename")
+    label="tagging.rename_tag"
+    disabled=renameDisabled
+  }}
 </div>

GitHub sha: 6b10ada7

This commit appears in #12818 which was approved by CvX. It was merged by jjaffeux.

This commit has been mentioned on Discourse Meta. There might be relevant details there: