# 如何通过插件自定义/覆盖主题监护人

**URL:** https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739
**Category:** Development
**Created:** [2021年二月15日 03:30 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739 "2021-02-15T03:30:06Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![hyd504](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hyd504/32/177122_2.png) [@hyd504](https://meta.discourse.org/u/hyd504)
#### Post date: [2021年二月15日 03:30 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739/1 "2021-02-15T03:30:06Z")

</div>

我正在开发一个插件，该插件会根据某些自定义逻辑，为每个不允许创建新主题的用户在 `user_custom_fields` 表中添加一个布尔值。

`user.custom_fields['can_create_topic'] = false;`

**我想做什么？**  
我想根据自定义逻辑，为某些用户隐藏“新建主题”按钮。

**问题**  
是否可以自定义 `can_create_topic` 的 guardian，使其额外检查 `user_custom_field`，以确定用户是否被允许创建新主题？

---

<div class="post-metadata">

### Author: ![neounix](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/neounix/32/215617_2.png) [@neounix](https://meta.discourse.org/u/neounix)
#### Post date: [2021年二月15日 09:50 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739/2 "2021-02-15T09:50:17Z")

</div>

> [@hyd504](#):
>
> 可以自定义 can\_create\_topic 吗？

是的，当然可以通过插件修改 Ruby 类。这是软件，很容易修改，并不是利用太阳帆或虫洞进行星际旅行，因此当然可以通过插件修改 Discourse 的行为：

> <https://github.com/discourse/discourse/blob/main/lib/guardian.rb>

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2021年二月15日 12:55 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739/3 "2021-02-15T12:55:01Z")

</div>

我不清楚您的具体使用场景，但最简单且安全的做法是将这些用户添加或移除至一个拥有创建话题权限的用户组中。

---

<div class="post-metadata">

### Author: ![hyd504](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hyd504/32/177122_2.png) [@hyd504](https://meta.discourse.org/u/hyd504)
#### Post date: [2021年二月15日 14:06 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739/4 "2021-02-15T14:06:49Z")

</div>

@pfaffman 这也是个好主意。不过我认为，如果我能重写 TopicGuardian 中的 can\_create\_topic? 方法，那会是更干净的解决方案。有没有类似的插件可以参考？

我不清楚的是，如何让我的 TopicGuardian 子类从插件中继承，并替换 Guardian 类中的 TopicGuardian，因为它是通过 mixin 方式引入的，而不是依赖注入。

---

<div class="post-metadata">

### Author: ![hyd504](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/hyd504/32/177122_2.png) [@hyd504](https://meta.discourse.org/u/hyd504)
#### Post date: [2021年二月15日 22:00 UTC](https://meta.discourse.org/t/how-to-customize-override-topic-guardian-through-a-plugin/179739/5 "2021-02-15T22:00:17Z")

</div>

好的，我想我已经找到答案了。我只需要在 `module ::TopicGuardian` 中实现 `can_create_topic?` 方法，它就能自动改变 TopicGuardian 的行为，而无需注入或将其注册到任何地方。此外，我可以在重写的方法中使用 `super` 方法，这样就不必总是手动将其与原始方法保持同步，以防后者发生变化。

我从这个主题中获得了帮助：[Overriding user\_guardian.rb in a plugin (no fork necessary!)](https://meta.discourse.org/t/overriding-user-guardian-rb-in-a-plugin-no-fork-necessary/174839)
