您好,
我希望更改所有标记为“ethan”的事件主题中初始帖子的所有权,将所有者从“system”更改为用户“Ethan_Hoom1”。我正在运行自托管实例,并且可以访问 Rails 控制台。
在查看了 Administrative Bulk Operations 和 Change ownership of all posts by a specific user 的建议后,我准备了以下脚本。在生产环境中运行它之前,我希望得到任何建议或最佳实践:
# 查找名称为“ethan”的标签对象
tag = Tag.find_by(name: "ethan")
# 如果未找到标签,立即停止
raise "Tag not found" unless tag
# 查找应成为帖子新所有者的用户
# username_lower 比 username 更安全(不区分大小写)
new_owner = User.find_by(username_lower: "ethan_hoom1")
# 如果未找到目标用户,立即停止
raise "New owner user not found" unless new_owner
# 查找系统用户账户
# 如果记录查找失败,则回退到 Discourse.system_user
system_user = User.find_by(username_lower: "system") || Discourse.system_user
# 如果找不到系统用户,立即停止
raise "System user not found" unless system_user
# 如果为 true,脚本将仅打印它将更改的内容
# 并且不会修改数据库中的任何内容
DRY_RUN = true
# 首次运行时可选的安全限制(例如 10 或 50)
# 设置为 nil 以处理所有匹配的帖子
LIMIT = nil
# 构建一个 ActiveRecord 查询,用于我们想要修改的帖子
scope = Post
# 连接帖子 → 主题 → 主题标签以便按标签过滤
.joins(topic: :topic_tags)
# 只针对每个主题中的第一个帖子
.where(post_number: 1)
# 只针对当前由系统用户拥有的帖子
.where(user_id: system_user.id)
# 只包含带有“ethan”标签的主题
.where(topic_tags: { tag_id: tag.id })
# 排除私人消息和已删除的主题
.where(topics: {
archetype: Archetype.default,
deleted_at: nil
})
# 如果设置了 LIMIT,则限制处理的帖子数量
scope = scope.limit(LIMIT) if LIMIT
# 分批迭代匹配的帖子,以避免内存问题
scope.find_each(batch_size: 100) do |first_post|
# 存储主题 ID 用于日志输出
topic_id = first_post.topic_id
# 如果启用了干运行模式,则不进行任何修改
if DRY_RUN
puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
next
end
begin
# 使用 Discourse 的官方所有权更改服务
PostOwnerChanger.new(
# 只更改第一个帖子的所有权
post_ids: [first_post.id],
# 包含该帖子的主题
topic_id: topic_id,
# 应成为新所有者的用户
new_owner: new_owner,
# 执行操作的用户(系统用户)
acting_user: system_user,
# 不要为此更改创建编辑修订版
skip_revision: true
).change_owner!
# 将成功记录到控制台
puts "Changed owner for topic #{topic_id} (post #{first_post.id})"
rescue => e
# 如果出现任何故障,记录错误但继续处理其他帖子
puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
end
end
问题:
- 对于这种情况,我应该注意
PostOwnerChanger的哪些注意事项或边缘情况? - 建议像可选行中显示的那样也更新
topic.user字段吗? - 对于这种批量处理,您对进一步的安全或性能改进有什么建议吗?
感谢您的帮助以及所有出色的文档!