# 扩展现有控制器？

**URL:** https://meta.discourse.org/t/extend-existing-controller/266411
**Category:** Development
**Created:** [2023年五月28日 01:59 UTC](https://meta.discourse.org/t/extend-existing-controller/266411 "2023-05-28T01:59:19Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 01:59 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/1 "2023-05-28T01:59:19Z")

</div>

大家好，我希望我发帖的地方没错。我正在为我的新 Discourse 网站开发一个插件。

我 fork 了示例仓库 [here](https://github.com/fletchmillcomm/hoa_forum)，实现了一个 Plugin Outlet，然后就卡住了，感到非常迷茫和困惑。我最近才开始掌握像 Laravel 这样的 MVC PHP 框架，但我对 JS 框架非常陌生。我以前从未接触过 Ruby、Rails 或 Ember。

# 问题

我的网站是为一个 HOA 社区设计的。我想为 **每个用户** 收集和保存一些额外的字段数据：

- `legal_name` (字符串)
- `is_owner` (布尔值)
- `is_resident` (布尔值)
- `building` (字符串) - 代表他们的楼号
- `unit` (字符串) - 代表他们的单元号
- …以及一些其他的内部变量，比如版主是否已确认他们。

我想让这些字段在用户注册时成为必填项。这意味着需要修改用户注册表单。我钩入了 `create-account-after-password` outlet 并显示了一些额外的字段，但这显然不能让它正常工作。

我认为我需要扩展 `app/assets/javascripts/discourse/app/controllers/create-account.js` 中的控制器，不仅是为了在提交时捕获新的表单值，_甚至是为了像使用站点名称 `this.siteSettings.title` 这样的（看似）基本功能_，在 `client.en.yml` 的翻译字段中使用！(现在我的注册表单中的额外字段的标题是，“你与 [缺失的 %{title} 值] 的关系是什么？” 这显然不好。)

我越是尝试寻找答案，就越是产生更多问题，而且问题越来越大。我尝试遵循的不同指南似乎是为不同版本的 Discourse 编写的。示例插件仓库中有我不理解的东西。客户端路由和服务器端路由有什么区别？插件和模块有什么区别？我太迷茫了。

如果有人能提供一些帮助，我将非常感激。提前谢谢大家。

---

<div class="post-metadata">

### Author: ![Moin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/moin/32/554653_2.png) [@Moin](https://meta.discourse.org/u/Moin)
#### Post date: [2023年五月28日 03:46 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/2 "2023-05-28T03:46:55Z")

</div>

> [@petermarkley](#):
>
> 我试图 **为每个用户** 收集和保存一些额外的字段数据：

我认为你可以通过 [Creating and configuring custom user fields](https://meta.discourse.org/t/create-and-configure-custom-user-fields/113192?u=moin) 来实现这一点。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 04:26 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/3 "2023-05-28T04:26:37Z")

</div>

谢谢！这并没有提供我认为想要的所有功能，但它确实让我停下来思考该功能是否能帮助我实现目标。

无论如何，我认为我仍然需要回答如何使用插件扩展现有控制器这个最初的问题。有这样的可能性吗？

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [2023年五月28日 04:38 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/4 "2023-05-28T04:38:05Z")

</div>

> [@petermarkley](#):
>
> 我试图收集和保存 **每个用户** 的一些额外字段数据

> [@petermarkley](#):
>
> 这并没有提供我认为想要的所有功能，但它确实让我停下来考虑该功能是否能帮助我实现目标。

保存它只是为了在某个地方显示？你想用这些数据做什么？我的印象是你想存储它以用于其他功能，而不是仅仅在论坛的某个地方显示它。

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2023年五月28日 05:56 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/6 "2023-05-28T05:56:28Z")

</div>

> [@petermarkley](#):
>
> 我试图 **为每个用户** 收集和保存一些额外的字段数据：  
> …  
> 我想在用户注册时将这些字段设为必填项。这意味着需要修改用户注册表单

无需任何编程即可使用 [Creating and configuring custom user fields](https://meta.discourse.org/t/create-and-configure-custom-user-fields/113192) 完成此操作。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 06:52 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/8 "2023-05-28T06:52:24Z")

</div>

> 你想用这些数据做什么？我以为你想把它们存储起来以实现其他功能，而不仅仅是在论坛的某个地方显示它们。

嗯，我最终的希望/设想是：

## 1. 分级管理

授予社区中每个单元的所有者仅对其单元居民的管理权限。

考虑到我们社区有近 200 个单元，使用群组功能来实现这一点似乎不可行。另请参阅下面的第 3 点，群组也会与之冲突。

## 2. 注册用户体验

在我看来，理想的用户体验是，注册表单上的“单元”下拉菜单能够根据用户在“楼栋”字段中的选择动态响应，从而仅提供该楼栋中的单元。（我打算在 Discourse 初始化时通过某种方式解析 JSON 配置文件来实现这一点。）

## 3. 字段隐私设置

我想让每个用户选择是否向其单元之外的其他用户隐藏其楼栋和/或单元号。

我的印象是，核心自定义字段功能仅提供每个字段的此选项（而不是每个用户的选项），并且 **仅** 对管理员可用，而不是对用户自己可用。

## 4. 精美样式

这更像是锦上添花的事情，但不是显示为“ **业主：** 是”，而是让系统了解这些字段的特殊性，以便在用户摘要中以不同的方式显示它们。例如，放置一个 SVG 契约图标，如果管理员已确认其身份（或为居民放置房屋图标），则显示一个勾号。之类的内容。

## 所以，是的……

也许我在这里太挑剔了，但我觉得一旦我掌握了实现核心功能所需的学习曲线，那么更小的愿望清单项目将变得几乎微不足道。

我社区的许多居民都是年长者，几乎没有或根本没有计算机知识。我严重担心一些居民不愿意采用和使用我的 Discourse 网站，_仅仅因为它很新而不是 Facebook_，更不用说地址隐私或楼栋/单元号的未经验证输入等实际使用问题了。

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2023年五月28日 08:12 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/9 "2023-05-28T08:12:49Z")

</div>

> [@petermarkley](#):
>
> 考虑到我们的社区有近200个单位，使用群组功能来实现这一点似乎并不可行。另请参阅下面的第3点，群组也会与之冲突。

群组可以很好地完成此任务，并且您可以轻松拥有200个群组。  
您所需要做的就是手动或以编程方式将字段映射到群组。但您可能还希望用户在注册后发送某种“证明”。  
您可以手动完成，自己编写代码，或者[使用Pavilion的自定义向导插件](https://custom-wizard.pavilion.tech/)来完成。

> [@petermarkley](#):
>
> 我的印象是，核心自定义字段功能仅为每个字段（而非每个用户）提供此选项

这是真的，但您可以让用户希望在其他地方公开显示该字段，即拥有一个“私有”建筑字段和一个“公共”建筑字段。

---

<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: [2023年五月28日 10:47 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/10 "2023-05-28T10:47:16Z")

</div>

如果你确实需要添加功能，你应该创建一个插件或主题组件，而不是分叉 Discourse。

> [@petermarkley](#):
>
> Signup UX

你可以在主题组件中做到这一点，所以你不需要插件，但如果你正在制作插件，你也可以在插件中包含前端更改。[Developing Discourse Plugins - Part 1 - Create a basic plugin](https://meta.discourse.org/t/developing-discourse-plugins-part-1-create-a-basic-plugin/30515)。寻找添加类似功能的插件也是一个好方法。有一个名为 all-the-plugins 的 Discourse 仓库，你可以用它来搜索示例。

> [@petermarkley](#):
>
> Field privacy settings

如建议的那样，拥有这些字段的公共版本和私有版本似乎是一个不错的解决方案，但你也可以在插件中添加用户字段，并控制如何以及是否将这些字段添加到序列化器中以显示它们。

> [@petermarkley](#):
>
> Fancy styling

这就是主题组件的作用。[Theme Developer Quick Reference Guide](https://meta.discourse.org/t/theme-developer-quick-reference-guide/110448) 可以作为开始。

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2023年五月28日 10:53 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/11 "2023-05-28T10:53:08Z")

</div>

> [@pfaffman](#):
>
> 你想创建一个插件或主题组件，而不是分叉 discourse。

我不认为 TS 打算分叉 discourse？？

> [@petermarkley](#):
>
> 我正试图为我的新 Discourse 开发一个插件

---

<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: [2023年五月28日 11:31 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/12 "2023-05-28T11:31:37Z")

</div>

> [@RGJ](#):
>
> 我不认为 TS 打算分叉 discourse？？

看起来他链接的仓库是一个分叉，而不是一个插件。

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2023年五月28日 12:45 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/13 "2023-05-28T12:45:04Z")

</div>

![image](https://global.discourse-cdn.com/meta/original/4X/a/0/e/a0ed0cb9efae8c86a755e0295716595804ba364f.png)

Forking `discourse-plugin-skeleton` 似乎是一个不错的起点，可以让我编写插件…

---

<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: [2023年五月28日 13:51 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/14 "2023-05-28T13:51:11Z")

</div>

说得对！我不知道我看到了什么！不知道我怎么会没注意到那是个 fork。🤷

我以为我查找了 `plugin.rb`……

---

<div class="post-metadata">

### Author: ![Lilly](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lilly/32/575047_2.png) [@Lilly](https://meta.discourse.org/u/Lilly)
#### Post date: [2023年五月28日 14:02 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/15 "2023-05-28T14:02:49Z")

</div>

没关系，我从这次谈话中学到了东西 😁

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 16:27 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/16 "2023-05-28T16:27:05Z")

</div>

感谢 @RGJ 为我澄清！😅 是的，我绝对不会仅仅因为这个原因就 fork Discourse 本身。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 16:37 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/17 "2023-05-28T16:37:08Z")

</div>

> 您还可以在插件中添加用户字段，并控制如何以及是否将这些字段添加到序列化器以显示它们。

这是否包括将它们添加到“创建帐户”模态表单中，并使其成为必填项？您能否为我指出任何有关如何执行此操作的示例或指南？

我已经阅读了您链接的“开发 Discourse 插件”的整个指南。我就是从那里开始的。最终，唯一真正展示如何扩展功能的只是创建[一个带有紫色触手的管理员页面](https://meta.discourse.org/t/developing-discourse-plugins-part-5-add-an-admin-interface/31761)。我已经为我的插件创建了一个可用的管理员页面，但我甚至不确定我是否需要它。它与我目前面临的问题无关，因此他们的示例对我的情况帮助不大。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 16:52 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/18 "2023-05-28T16:52:11Z")

</div>

> 群组可以很好地满足该目的，并且您可以轻松拥有 200 个群组

实际上，这将在 400 到 600 之间，以涵盖所有排列（每个单元的所有者、居民或附属用户）。但这将如何运作？ 200 个群组是否都可以向用户显示相同的内容，这样它只会显示“所有者”，而不是“所有者 187”之类的东西？

这是一个非常细节的问题，但内部群组 ID 会在任何地方暴露给最终用户吗？例如，在 URL 中？如果用户将他们的单元号设置为私有，有人可以通过将群组 ID 与其他用户进行比较来找出它吗？

在我看来，创建仅 3 个群组（所有者、居民和附属用户——或者仅 2 个：所有者和居民）可能会取得更好的效果。也许我可以像您说的那样适当地分配这些群组，然后阻止某些操作，如果用户试图审核错误单元的居民？

我想，如果阻止此类操作完全不可能，那么我确实只能创建 600 个群组……并且只能希望我们不会有任何用户产生“黑客”系统并泄露任何人信息的聪明想法。

---

<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: [2023年五月28日 18:21 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/19 "2023-05-28T18:21:59Z")

</div>

> [@petermarkley](#):
>
> Grant owners of each unit in the community moderator powers over ONLY the residents of their unit.

等等。什么？所以如果我是一名租客，我在论坛上说了什么，我的房东就可以更改我的话？主题只属于一个类别，所以你会有只有业主和租客之间的对话。

这说不通。而且真的没有简单的方法可以进行主题级别的权限设置。

我认为您会想要一些按建筑分组和分类，但按单元控制根本没有意义。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 18:34 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/20 "2023-05-28T18:34:10Z")

</div>

我没有提到过主题级别的权限。

也许“版主”这个词用错了？我不知道。（我以前从未使用过 Discourse。）

我说的是 **按用户** 批准或移除论坛访问权限。所以，是的，你的房东不能更改你的言论，但他们有权确认你作为居民的注册，如果你变成了一个捣乱者，他们可以禁言或封禁你。帖子和主题都受到网站工作人员的同等审核，以遵守内容政策，而不是由业主审核。

我的目标是将论坛访问权限尽可能地与每个房产本身的法律权力链联系起来。任何合法拥有房产的已确认业主永远不应被封禁，但如果他们发布了违反政策的帖子，该帖子可以被工作人员删除。然而，如果他们出售了房产，他们的“业主”身份将立即被撤销，可能会导致被移除出网站（除非他们选择“附属”身份并获得新房产所有者的批准）。

在我们的社区中，同一栋楼的一个单元与另一个单元之间没有关系，除了物理上相连。仅此而已。按楼宇对人们进行分组基本上是一个化妆品用户体验的决定；在这里任命整个楼宇的负责人是没有意义的。

---

<div class="post-metadata">

### Author: ![petermarkley](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/petermarkley/32/307825_2.png) [@petermarkley](https://meta.discourse.org/u/petermarkley)
#### Post date: [2023年五月28日 18:55 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/21 "2023-05-28T18:55:46Z")

</div>

我发现了这个：[Add a custom per-user setting in a plugin](https://meta.discourse.org/t/add-a-custom-per-user-setting-in-a-plugin/94048)

在评论中，一位用户说他“修补了一个控制器”。他有一个位于 `assets/javascripts/discourse/initializers/` 的 `.js.es6` 文件，其中引用了一个名为 `api.modifyClass()` 的方法……

嗯嗯嗯 🤔 也许我发现了点什么。

---

<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: [2023年五月28日 19:04 UTC](https://meta.discourse.org/t/extend-existing-controller/266411/22 "2023-05-28T19:04:33Z")

</div>

太好了！就是这样！

我建议您在决定具体要做什么之前，先熟悉一下论坛。

我认为，如果由一小群人批准用户加入网站，而不是让每个业主都控制对网站的访问，会更容易。如果业主说了算，当有人出售房产时会发生什么？届时谁来决定？如果业主不关心他们的租户是否能成为论坛成员，那该怎么办？我认为让综合大楼的经理来决定会更有意义，而且可能不需要插件。

[下一頁](https://meta.discourse.org/t/extend-existing-controller/266411.md?page=2)
