# 将 Discourse 升级到 Zeitwerk

**URL:** https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337
**Category:** Development
**Tags:** dev-news
**Created:** [2019 年9 月 11 日 21:02 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337 "2019-09-11T21:02:46Z")
**Posts on this page:** 15
**Page:** 1

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年9 月 11 日 21:02 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/1 "2019-09-11T21:02:46Z")

</div>

Rails 6 默认提供两种自动加载模式：`zeitwerk` 和 `classic`。在该拉取请求 [DEV: Upgrading Discourse to Rails 6 by KrisKotlarek · Pull Request #8083 · discourse/discourse · GitHub](https://github.com/discourse/discourse/pull/8083) 中，我将 Rails 升级到了 6.0.0 版本，并暂时使用 classic 自动加载器作为过渡方案。尝试切换到 Zeitwerk 会很有意思。

Zeitwerk 是一个高效且线程安全的 Ruby 代码加载器。只要项目遵循命名规范，Zeitwerk 就能找到正确的文件并按需或预先加载它们，而无需任何 `require` 或 `require_dependency`。此外，根据这篇文章 [https://weblog.rubyonrails.org/2019/2/22/zeitwerk-integration-in-rails-6-beta-2/，它还可能为应用程序带来轻微的性能提升。](https://weblog.rubyonrails.org/2019/2/22/zeitwerk-integration-in-rails-6-beta-2/%EF%BC%8C%E5%AE%83%E8%BF%98%E5%8F%AF%E8%83%BD%E4%B8%BA%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E5%B8%A6%E6%9D%A5%E8%BD%BB%E5%BE%AE%E7%9A%84%E6%80%A7%E8%83%BD%E6%8F%90%E5%8D%87%E3%80%82)

为了实现这一目标，我需要完成以下几个步骤：

1. 修改部分类的名称以符合 Rails 命名规范。例如，文件 `canonical_url.rb` 应定义 `CanonicalUrl` 类，而不是 `CanonicalURL`。同样，文件 `ondiff.rb` 应定义 `Onpdiff` 类，而不是 `ONPDiff`。另一种方法是为项目挂载自定义推断器（inflector），但我认为遵循规范可能是更好的选择 - [GitHub - fxn/zeitwerk: Efficient and thread-safe code loader for Ruby · GitHub](https://github.com/fxn/zeitwerk#custom-inflector)

2. 与上一点类似，按照规范，位于 `validations` 目录中的自定义验证应包裹在 `Validations` 模块中。此外，某些验证继承自 `EachValidator`，应无需命名空间即可访问。我计划将它们移至单独的目录，并添加到自动加载路径中。

3. 移除所有 `require_dependency`，并确保项目正常运行。

4. 移除所有 `require`，并确保 Discourse 正常运行。

5. 确保所有插件都能访问所需的依赖项。目前我还不知道如何实现这一点。我打算先让 Discourse 在不加载任何插件的情况下运行。

当然，仍有许多未知问题需要解决。我会持续向您汇报进展。如果您有兴趣查看，我在此处开始尝试：[Commits · KrisKotlarek/discourse · GitHub](https://github.com/lis2/discourse/commits/zeitwerk)

如果您发现实施 Zeitwerk 存在任何弊端，或认为我遗漏了某些内容，请随时告知。

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年9 月 14 日 05:51 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/2 "2019-09-14T05:51:12Z")

</div>

我在 Zeitwerk 方面取得了一些进展，但我改变了方法。我最初的计划是修改 Discourse 中所有不符合 Zeitwerk 文件名约定的地方。在修复了几处问题后，我意识到这仅仅是冰山一角，并且注意到如果继续沿着这条路走，拉取请求（PR）将难以阅读，也难以有信心地合并到主分支。例如，常规目录下的所有作业类都应具有 `Regular` 命名空间，`Onceoff` 和 `Scheduled` 同理。

我决定稍微退一步，思考一种更具演进性而非革命性的方法。

我决定最好引入一个自定义的 Inflector，以覆盖所有不符合 Zeitwerk 约定的文件。这样最大的好处是，我们可以先部署这一小改动，一旦我们对 Zeitwerk 感到满意且没有出现性能下降，就可以开始以合理的小型拉取请求逐个修复约定文件。

我发现有些问题无法通过自定义 Inflector 解决，因此我进行了额外的修复以确保其正常工作。

拉取请求仍在进行中，但在此阶段，我已经能够使用 Zeitwerk 和默认插件运行 Discourse，运行所有测试用例，并顺利执行基准测试。

我首先希望达到所有测试用例都通过的稳定状态。现在，我可以有信心地逐个移除所有的 `require_dependency`，并测试官方插件。一旦一切准备就绪，我将在此帖子中分享基准测试结果。

目前，如果您想了解进展，可以查看这个草稿 PR：[DEV: Upgrading Discourse to Zeitwerk by KrisKotlarek · Pull Request #8098 · discourse/discourse · GitHub](https://github.com/discourse/discourse/pull/8098)

最重要的文件是那个自定义的 Zeitwerk Inflector：[DEV: Upgrading Discourse to Zeitwerk by KrisKotlarek · Pull Request #8098 · discourse/discourse · GitHub](https://github.com/discourse/discourse/pull/8098/files#diff-1d11f8dea7245fa4921be68dbc40a1d1)

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年9 月 15 日 03:16 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/3 "2019-09-15T03:16:16Z")

</div>

为了让插件正常工作，我需要再提交几个小的拉取请求。一旦它们被合并，我认为 Discourse 上的测试应该能通过。

- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #25 · discourse/discourse-translator · GitHub](https://github.com/discourse/discourse-translator/pull/25)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #51 · discourse/discourse-canned-replies · GitHub](https://github.com/discourse/discourse-canned-replies/pull/51)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #33 · discourse/discourse-chat-integration · GitHub](https://github.com/discourse/discourse-chat-integration/pull/33)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #29 · discourse/discourse-cakeday · GitHub](https://github.com/discourse/discourse-cakeday/pull/29)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #45 · discourse/discourse-topic-voting · GitHub](https://github.com/discourse/discourse-voting/pull/45)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #4 · discourse/discourse-perspective-api · GitHub](https://github.com/discourse/discourse-perspective-api/pull/4)
- [Update translations by discourse-translator-bot · Pull Request #45 · discourse/discourse-akismet · GitHub](https://github.com/discourse/discourse-akismet/pull/45)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #52 · discourse/discourse-assign · GitHub](https://github.com/discourse/discourse-assign/pull/52)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #4 · discourse/discourse-backup-uploads-to-s3 · GitHub](https://github.com/discourse/discourse-backup-uploads-to-s3/pull/4)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #4 · discourse/discourse-saved-searches · GitHub](https://github.com/discourse/discourse-saved-searches/pull/4)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #6 · discourse/discourse-prometheus-alert-receiver · GitHub](https://github.com/discourse/discourse-prometheus-alert-receiver/pull/6)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #10 · discourse/discourse-github · GitHub](https://github.com/discourse/discourse-github/pull/10)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #1 · discourse/discourse-logster-rate-limit-checker · GitHub](https://github.com/discourse/discourse-logster-rate-limit-checker/pull/1)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #2 · discourse/discourse-auto-deactivate · GitHub](https://github.com/discourse/discourse-auto-deactivate/pull/2)
- [FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #4 · discourse/discourse-calendar · GitHub](https://github.com/discourse/discourse-calendar/pull/4)
- [[WIP] FIX: Use top-level namespace for base classes by KrisKotlarek · Pull Request #7 · discourse/discourse-policy · GitHub](https://github.com/discourse/discourse-policy/pull/7)

我还检查了在 Rails 6.0.0 使用 Classic 自动加载器以及 Rails 6.0.0 使用 Zeitwerk 时的性能。

| 测试 | Classic | Zeitwerk | 百分比 |
| --- | --- | --- | --- |
| categories-50 | 32 | 26 | 81.25 |
| categories-75 | 37 | 29 | 78.38 |
| categories-90 | 47 | 35 | 74.47 |
| categories-99 | 67 | 49 | 73.13 |
| home-50 | 30 | 29 | 96.67 |
| home-75 | 37 | 31 | 83.78 |
| home-90 | 44 | 40 | 90.91 |
| home-99 | 67 | 52 | 77.61 |
| topic-50 | 35 | 35 | 100.00 |
| topic-75 | 36 | 36 | 100.00 |
| topic-90 | 48 | 36 | 75.00 |
| topic-99 | 57 | 58 | 101.75 |
| categories\_admin-50 | 51 | 48 | 94.12 |
| categories\_admin-75 | 62 | 50 | 80.65 |
| categories\_admin-90 | 89 | 66 | 74.16 |
| categories\_admin-99 | 135 | 101 | 74.81 |
| home\_admin-50 | 48 | 47 | 97.92 |
| home\_admin-75 | 58 | 49 | 84.48 |
| home\_admin-90 | 67 | 64 | 95.52 |
| home\_admin-99 | 101 | 81 | 80.20 |
| topic\_admin-50 | 48 | 48 | 100.00 |
| topic\_admin-75 | 55 | 49 | 89.09 |
| topic\_admin-90 | 63 | 65 | 103.17 |
| topic\_admin-99 | 92 | 69 | 75.00 |
| load\_rails | 2617 | 2165 | 82.73 |
| rss\_kb | 282428 | 315684 | 111.78 |
| pss\_kb | 270491 | 303504 | 112.20 |

结果并不总是一致，因此请谨慎看待这些数据。

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年9 月 15 日 04:54 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/4 "2019-09-15T04:54:40Z")

</div>

这里的中间值不一致程度有点奇怪，我不明白结果为何波动如此之大

没想到加载器竟会有任何影响

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年9 月 15 日 05:19 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/5 "2019-09-15T05:19:28Z")

</div>

我又试了一次，结果如下：

| 测试项 | Classic | Zeitwerk | 百分比 |
| --- | --- | --- | --- |
| categories-50 | 25 | 25 | 100.00 |
| categories-75 | 26 | 26 | 100.00 |
| categories-90 | 37 | 33 | 89.19 |
| categories-99 | 57 | 48 | 84.21 |
| home-50 | 26 | 26 | 100.00 |
| home-75 | 27 | 28 | 103.70 |
| home-90 | 38 | 35 | 92.11 |
| home-99 | 60 | 50 | 83.33 |
| topic-50 | 27 | 26 | 96.30 |
| topic-75 | 35 | 27 | 77.14 |
| topic-90 | 41 | 33 | 80.49 |
| topic-99 | 54 | 50 | 92.59 |
| categories\_admin-50 | 48 | 50 | 104.17 |
| categories\_admin-75 | 60 | 61 | 101.67 |
| categories\_admin-90 | 76 | 71 | 93.42 |
| categories\_admin-99 | 122 | 122 | 100.00 |
| home\_admin-50 | 47 | 46 | 97.87 |
| home\_admin-75 | 58 | 55 | 94.83 |
| home\_admin-90 | 66 | 63 | 95.45 |
| home\_admin-99 | 99 | 121 | 122.22 |
| topic\_admin-50 | 50 | 49 | 98.00 |
| topic\_admin-75 | 62 | 50 | 80.65 |
| topic\_admin-90 | 72 | 65 | 90.28 |
| topic\_admin-99 | 103 | 74 | 71.84 |
| load\_rails | 2675 | 2216 | 82.84 |
| rss\_kb | 279924 | 315240 | 112.62 |
| pss\_kb | 267659 | 303026 | 113.21 |

我们可以尝试另一种基准测试方法。你觉得增加迭代次数、让测试运行一个小时怎么样？此外，与其取最佳结果，不如比较每次实验的平均值。这样可能会得到更稳定的数据。你怎么看？

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年9 月 16 日 22:32 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/6 "2019-09-16T22:32:41Z")

</div>

在我为插件提交的拉取请求中，您会注意到许多修复都涉及全局命名空间中的搜索问题。

我将类似以下的代码：

```plaintext
module ::Jobs
  class TranslatorMigrateToAzurePortal < Jobs::Onceoff

```

修改为：

```plaintext
module ::Jobs
  class TranslatorMigrateToAzurePortal < ::Jobs::Onceoff

```

这个解决方案让我有些困惑：为什么在 Zeitwerk 之前它能正常工作？当某段代码能运行但实际上不应该运行时，这个问题总是很棘手 🙂

我认为我在经典自动加载器的描述中找到了一个潜在答案（[https://guides.rubyonrails.org/autoloading\_and\_reloading\_constants\_classic\_mode.html#resolution-algorithms）——“如果未找到，则算法会沿着创生引用（cref）的祖先链向上遍历”。](https://guides.rubyonrails.org/autoloading_and_reloading_constants_classic_mode.html#resolution-algorithms%EF%BC%89%E2%80%94%E2%80%94%E2%80%9C%E5%A6%82%E6%9E%9C%E6%9C%AA%E6%89%BE%E5%88%B0%EF%BC%8C%E5%88%99%E7%AE%97%E6%B3%95%E4%BC%9A%E6%B2%BF%E7%9D%80%E5%88%9B%E7%94%9F%E5%BC%95%E7%94%A8%EF%BC%88cref%EF%BC%89%E7%9A%84%E7%A5%96%E5%85%88%E9%93%BE%E5%90%91%E4%B8%8A%E9%81%8D%E5%8E%86%E2%80%9D%E3%80%82)

Zeitwerk 更加严格。在我尝试加载修复前的代码时，它报错说找不到 `Jobs::Jobs::Onceoff`。

Sam 在拉取请求 [FIX: Use top-level namespace for base classes · discourse/discourse-prometheus-alert-receiver@ef9c238 · GitHub](https://github.com/discourse/discourse-prometheus-alert-receiver/commit/ef9c238a6fabc3a9ca238664adb3dc594dc709ee) 中建议，与其使用 `< ::Jobs::Onceoff`，不如直接使用 `< Onceoff`，他说得对。我验证了不带命名空间也能正常工作。我认为使用 `::` 是明确表示我们继承自 Discourse 核心类，不过两种方式都可以。

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年9 月 17 日 06:15 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/7 "2019-09-17T06:15:08Z")

</div>

我认为当代码靠得这么近时，这样读起来很顺畅：

```plaintext
module ::Jobs
  class TranslatorMigrateToAzurePortal < Onceoff

```

但如果代码开始分散，显式声明会更有意义……例如：

```plaintext
module ::Jobs
  [50 行省略]
  class TranslatorMigrateToAzurePortal < ::Jobs::Onceoff

```

不过，我对此持中立态度，所以两种写法我都可以接受。`::Jobs::Onceoff` 足够简短且非常明确，因此我们现在可以先采用这种方式。

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年10 月 2 日 00:59 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/8 "2019-10-02T00:59:24Z")

</div>

我很希望能尽快合并这个。@kris.kotlarek 现在是否可以合并了？时机正好，因为我们刚发布了 beta 版本。

> <https://github.com/discourse/discourse/pull/8098>
>
> Update from Classic to Zeitwerk autoloader. 
> 
> \*\*This pull request is a little …bit risky, so please don't merge in a super busy period.\*\* 
> 
> Could you review if that looks fine?
> 
> Before merging that, I think that it would be good to merge fixes for plugins:
> https://github.com/discourse/discourse-translator/pull/25
> https://github.com/discourse/discourse-canned-replies/pull/51
> https://github.com/discourse/discourse-cakeday/pull/29
> https://github.com/discourse/discourse-voting/pull/45
> https://github.com/discourse/discourse-perspective-api/pull/4
> https://github.com/discourse/discourse-calendar/pull/4
> https://github.com/discourse/discourse-prometheus/pull/4
> 
> What can go wrong?
> \- If I missed any \`::\` in front \`Jobs::Onceoff\`, \`Jobs::Base\` or \`Jobs::Scheduled\` it may crash
> \- I changed Demon::Base to Demon::DemonBase, so any third party plugin relaying on that class needs to be updated 
> \- If I miss any typos like here: https://github.com/discourse/discourse/pull/8098/commits/1050ab0440dbad1f1f0d77e8ea8558ab9b552040
> 
> Details about approach are documented here: https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年10 月 2 日 01:13 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/10 "2019-10-02T01:13:03Z")

</div>

让我把最近的 master 分支变基到那里，并确保它仍然能正常工作，我今天会完成。

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年10 月 2 日 03:37 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/11 "2019-10-02T03:37:28Z")

</div>

@sam 我认为我们可以开始了。我已基于最新的 master 分支进行了变基，并对 Webauthn 做了小幅调整。  
我检查了以下三项：  
 在本地运行服务器并点击测试，确保其按预期工作  
 运行测试规范  
 下载所有官方插件，并确保插件的测试规范通过（我们需要先合并针对插件的调整）

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年10 月 2 日 04:00 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/12 "2019-10-02T04:00:18Z")

</div>

好的，我合并这个。看看结果如何！

---

<div class="post-metadata">

### 作者： ![kris.kotlarek](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/kris.kotlarek/32/176919_2.png) [@kris.kotlarek](https://meta.discourse.org/u/kris.kotlarek)
#### 发布日期： [2019 年10 月 2 日 04:06 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/13 "2019-10-02T04:06:56Z")

</div>

我们是否也可以合并插件的修复？否则，如果您尝试运行带有插件的 Discourse，将会失败

> <https://github.com/discourse/discourse-translator/pull/25>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff and Jobs::Base witho…ut going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-canned-replies/pull/51>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff and Jobs::Base witho…ut going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-cakeday/pull/29>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff and Jobs::Base witho…ut going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-topic-voting/pull/45>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff and Jobs::Base witho…ut going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-perspective-api/pull/4>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff and Jobs::Base witho…ut going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-calendar/pull/4>
>
> Zeitwerk is failing when we are searching for Jobs::Onceoff, Jobs::Base and Jobs…::Scheduled without going back to the top-level namespace (this is correlated to the fact that we got Onceoff base class and module with the same name). 
> 
> I noticed that in plugins we are using sometimes :: and sometimes not and that gives me comfort that this change will not break anything.
> 
> Travis error: https://travis-ci.org/discourse/discourse/jobs/585072364

> <https://github.com/discourse/discourse-prometheus/pull/4>
>
> This is a temporary and hacky solution until deploying of Zeitwerk for core Disc…ourse. In that PR https://github.com/discourse/discourse/pull/8098 demon base class was modified for Zeitwerk
> 
> The goal is here is the ability to safely merge that code before move Discourse to Zeitwerk.

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年10 月 2 日 04:29 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/14 "2019-10-02T04:29:30Z")

</div>

请继续合并！

---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年10 月 2 日 05:11 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/15 "2019-10-02T05:11:36Z")

</div>



---

<div class="post-metadata">

### 作者： ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### 发布日期： [2019 年10 月 2 日 05:19 UTC](https://meta.discourse.org/t/upgrading-discourse-to-zeitwerk/128337/16 "2019-10-02T05:19:55Z")

</div>

现在已合并！如果有任何插件作者在此遇到困难，请在新的专用主题中告诉我们！

干得漂亮，Kris！！！
