简介
从 Discourse 3.2.0.beta3 版本开始,Discourse 主题/组件可以利用迁移(migrations)功能来无缝地演进和更改其设置。此功能通过以受控方式处理设置更改,确保主题更新不会中断现有安装。
何时使用迁移
迁移特别有用的常见场景包括:
- 更改设置的类型(例如,从逗号分隔的字符串更改为列表)。
- 重命名设置。
- 修改存储在设置中的数据的结构或格式。
在这些场景中,如果在 settings.yml 文件中更改了设置的类型或名称而没有附带迁移,则在设置中已从默认值更改的现有安装在更新主题时将丢失所做的更改,并可能导致中断。
为确保在更新主题设置时顺利过渡,主题开发者应提供一个迁移,指示 Discourse 核心如何将符合旧版 settings.yml 状态迁移到新版本。
迁移文件
迁移是位于主题的 migrations/settings 目录中的 JavaScript 文件,遵循命名约定 XXXX-migration-name.js。XXXX 前缀是一个版本号,从 0001 开始并按顺序递增,它决定了执行顺序。
名称应是对迁移目的的简洁描述,仅限于字母数字字符、连字符,长度不超过 150 个字符。迁移按其版本的数字值升序执行。
我们建议第一个迁移从 0001 开始,第二个迁移从 0002 开始,依此类推。请注意,如果迁移的版本低于 1000,则版本必须用前导零填充以使其成为 4 位数,因为迁移文件名必须以 4 位数字开头。出于同样的原因,目前一个主题中不可能有超过 9999 个迁移,但我们将来可能会更改这一点。
迁移函数
标准的 JavaScript 特性,如类、函数、数组、Map 等,都可供迁移使用。Discourse 核心的唯一要求是每个迁移文件必须导出一个作为入口点的默认函数。此函数接收一个代表已修改主题设置的 Map 对象,并返回一个反映所有设置所需最终状态的 Map 对象。
示例
重命名主题设置:
// filename: 0001-rename-old-setting.js
export default function migrate(settings) {
if (settings.has("old_setting_name")) {
settings.set("new_setting_name", settings.get("old_setting_name"));
settings.delete("old_setting_name");
}
return settings;
}
此迁移应伴随在 settings.yml 文件中重命名设置。
将逗号分隔的字符串设置转换为正确的列表:
// filename: 0001-convert-string-setting-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split(",");
settings.set("list_setting", list.join("|"));
}
return settings;
}
与上一个示例类似,此迁移应伴随在 settings.yml 文件中将设置类型从 string 更改为 list。
重命名枚举设置的选项:
// filename: 0001-rename-enum-choice.js
export default function migrate(settings) {
if (settings.get("enum_setting") === "old_option") {
settings.set("enum_setting", "new_option");
}
return settings;
}
向列表设置添加新项:
// filename: 0001-add-item-to-list.js
export default function migrate(settings) {
if (settings.has("list_setting")) {
const list = settings.get("list_setting").split("|");
list.push("new_item");
settings.set("list_setting", list.join("|"));
} else {
settings.set("list_setting", "new_item");
}
return settings;
}
执行和错误处理
迁移在主题安装和更新期间自动运行。它们只执行一次;如果在成功执行后更改了迁移,它将不会再次运行。如果迁移失败,更新过程将停止,并提供有关发生错误的错误消息。
如果迁移中存在导致设置状态损坏的错误,修复问题的正确方法是创建一个新的迁移来纠正损坏的状态,而不是修改原始迁移。
本文档已版本控制 - 在 github 上建议更改。