Renaming tags in the rails console

Continuing the discussion from Can’t fix tag names with dots/periods:


Can anyone provide a tested guide on how to rename tags in the rails console? I have no experience using the rails console and don’t want to mess up the database…


SSH into your server

cd /var/discourse
./launcher enter app
rails c

t = Tag.find_by_name('oldname') = 'newname'

Is there also a way to change a specific tag in all topics? I renamed my domain once, there was a method to rewrite all references to the old domain do the new one. Can this also be done with tags? I want to rename a tag, but not confuse users with non-existing tags.

Edit, solved it with tag synonyms :tada: Although it’s far from ideal, since it will continue the use of old tags and it’s shown in my tags overview and auto-complete. I would really want to replace it fully and obsolete the old one.


Honest question - how is renaming the tag not sufficient for this?

1 Like

Well for example when I use the tag chat here and may others as well in different topics, and then you rename it to #chats. Then the #chat tag will be pointing to an non-existing tag because it’s not renamed. So the renaming works fine for topic titles, but not for within the topic comments when people used them already. Or am I missing something?

Extra thanks @RGJ , worked like a breeze :pray: :pray: :pray:

1 Like

I guess there is no way to rename existing tags used in topics by users? So not the tags in topic titles, but really in the comments.

Use at your own risk!

Do this after you have renamed #foo to #bar

Post.where("raw like '%#foo%'").each do |p|
  p.raw = p.raw.gsub(/#foo\b/, '#bar')!
1 Like

Looks cool! Thanks for the heads-up. Backups will mitigate the risk :nerd_face:.

For my understanding, "raw like '%#foo%'", is that strict matching? In the sense of, what if you have tag #access which needs to be renamed to #access_granted, would "raw like '%#access%'" match both #access and #access_granted? Because in that case existing comments that already use #access_granted could maybe be renamed to #accessaccess_granted.

To compare it to the grep command, the switch --word-regexp helps out and makes sure you match whole words only.

From the man page:

Select only those lines containing matches that form whole words. The test is that the matching substring must either be at the beginning of the line, or preceded by a non-word constituent character. Similarly, it must be either at the end of the line or followed by a non-word constituent character. Word-constituent characters are letters, digits, and the underscore.

Does this command work similar? Of course I can find out by doing the backup and run the command. But just to understand the risks, if you know this of course. Otherwise, YOLO.

The "raw like '%#foo%'" is indeed not strict matching, but it does not need to be. Because a LIKE % query is very expensive performance wise, I chose to not make it even worse by requiring a non-word-character after it. The where query is just there to pre-select - you could actually do Post.all.each and it would work as well (albeit much slower).

The actual replacing is being done by the gsub and the \b ensures that there is a word boundary after
the tag, i.e. the tag ends there.

So any posts containing #access_granted would match, and the inner code would execute, but the gsub would not do anything in that case.

irb(main):010:0> "Tag #access is here".gsub(/#access\b/, "#access_granted")
=> "Tag #access_granted is here"
irb(main):011:0> "Tag #access_granted is here".gsub(/#access\b/, "#access_granted")
=> "Tag #access_granted is here"
1 Like

I want to run this now:

Post.where("raw like '%#access%'").each do |p|
  p.raw = p.raw.gsub(/#access\b/, '#strategic_access')!

Post.where("raw like '%#feedback%'").each do |p|
  p.raw = p.raw.gsub(/#feedback\b/, '#digital_feedback')!

But I get an error bash: syntax error near unexpected token “raw like ‘%#access%’”'andbash: syntax error near unexpected token "raw like '%#feedback%'"', before I start guessing, does the # need to be escaped?

:point_up: it was supposed to come after this, the code should be executed within rails c


Oh yes, I didn’t even notice the bash error. I should get more sleep… Thanks!!


This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.