I had to do a major migration and had to do quite some DuckDuckGo-ing to be able to migrate everything the way I wanted to. So I’ve now extended the script from @riking to do the following:
- Require less typing
- Allow tagging all topics of a category at once
- Update the topic count after moving topics from one category to another
- Leave the “About the xxx category” topics untouched
Here’s how to use it (as suggested by @riking you should make a backup before doing this):
cd /var/discourse
./launcher enter app
There you should create a file named “MigrationCategory.rb” and copy the following into it:
class MigrationCategory < Category
# Overwriting this to be able to also find sub-categories.
def self.find_by_slug(category_slug)
self.where(slug: category_slug).first
end
def self.retag(category_slug, tag_slugs)
category = self.find_by_slug(category_slug)
tags = []
tag_slugs.each do |tag_slug|
tags.push(Tag.find_or_create_by(name: tag_slug))
end
self.get_category_topics(category).each do |topic|
topic.tags = tags
end
end
def self.move(category_slug_from, category_slug_to)
from = self.find_by_slug(category_slug_from)
to = self.find_by_slug(category_slug_to)
# Move to new category.
topics = self.get_category_topics(from)
topics.update_all(category_id: to.id)
# Update topic counts in from and to category.
topic_count_from = self.get_category_topics(from).count
Category.where(id: from.id).update_all(topic_count: topic_count_from)
topic_count_to = self.get_category_topics(to).count
Category.where(id: to.id).update_all(topic_count: topic_count_to)
end
# The "About the ... category" topic doesn't count.
def self.get_category_topics(category)
topics = Topic.where(category_id: category.id)
about_topic = Topic.where(id: category.topic_id).first
topics_without_about_topic = topics.where.not(id: about_topic.id)
return topics_without_about_topic
end
end
Then do this: rails c. Wait until the rails-console has started and import the file you just created with require '/var/www/discourse/MigrationCategory.rb'
Now everything is set up (but don’t leave the rails-console). You can start tagging topics like this:
MigrationCategory.retag('category-1-slug', ['tag1', 'tag2'])
You can move topics between categories like this:
MigrationCategory.move('category-1-slug', 'category-2-slug')