对于后端开发者来说,修改/扩展 Discourse 有多“困难”

您好,

我是一名拥有一些后端经验的机器学习工程师。我的前端技能几乎为零/非常薄弱。

我想托管一个小型论坛,需要以下功能:

  • 轻松地按多个标签过滤帖子
  • 某些类别需要用户登录后才能查看
  • 注册需要管理员批准
  • 网站顶部可能有一个图片轮播

这类功能是否难以实现?我查看了一些插件的代码,虽然实际实现部分很简短且易于阅读,但看起来很难编写。

2 个赞

我和你的情况一样。我มีประสบการณ์ด้านหลังบ้านด้วย nodejs และเคยทำด้านหน้าบ้านด้วย html/css/javascript มาบ้าง แต่ส่วนใหญ่จะทำด้านหลังบ้านมากกว่า มีโค้ดจำนวนมากที่ดูเหมือนจะเป็นโค้ดเฉพาะสำหรับ discourse หรือ ruby หรือเป็นรูปแบบการเขียนโค้ดที่มีความคิดเห็นเป็นของตัวเอง แม้ว่าฉันจะรู้ javascript แต่โค้ดเบสของ discourse ก็ดูน่ากลัวและซับซ้อนสำหรับฉัน ฉันกำลังคิดอย่างจริงจังที่จะลองรัน a.i. ของตัวเองในเครื่อง ซึ่งฉันสามารถป้อนโค้ดเบสทั้งหมดเข้าไปได้ จากนั้นจึงถามคำถามเกี่ยวกับสิ่งที่ฉันต้องการทำ นอกเหนือจากนั้น สิ่งที่ฉันทำได้คืออ่านโค้ด ปลั๊กอิน ฯลฯ ที่มีอยู่ และพยายามทำความเข้าใจให้ดีที่สุด หากคุณสนใจที่จะแบ่งปันความรู้หรือเรียนรู้ไปด้วยกัน ฉันก็เปิดรับ :slight_smile:

1 个赞

是的,学习曲线相当陡峭。但您提到的所有功能都已存在,并且不需要编码。

都包含在核心 Discourse 中,而

可以使用现有的主题组件实现。

5 个赞

我非常想在 Udemy 上看到一些关于 discourse 开发的视频课程。告诉我该给谁送钱。:dollar_banknote::dollar_banknote::dollar_banknote:

2 个赞

无需为此进行调整,API 已支持。您也可以从前端完成此操作!我创建了一个“小部件”(Glimmer 组件!)来专门执行此操作!:

此组件可在右侧边栏块和布局中运行。

1 个赞

这可以用来创建嵌套层次结构吗?

我正在考虑的论坛面向的是从未接触过类似论坛的在线讨论的老年人。

对他们来说,能够导航传统的论坛式嵌套结构会很好。

1 个赞

嵌套请使用 Categories。

2 个赞

许多 Discourse 实例都选择了这种方式,请看:

2 个赞

离题了,但这个功能在这里非常方便,我喜欢我们的“使用人工智能解释”功能

在给定上下文中,“MLE”是指机器学习工程师。这是一位专业人士,专门使用数据和算法来构建模型,使机器能够执行特定任务,而无需为这些特定任务进行显式编程。他们通常拥有扎实的计算机科学、统计学和编程背景,并且他们的专业知识倾向于关注技术的后端方面,例如构建和部署预测模型以及其他机器学习产品。当原帖提到“MLE”时,他们表明自己是机器学习工程师,熟悉后端开发,但缺乏前端开发经验。

5 个赞

关于此事的几点思考。

开发付费 Discourse 课程

在 Udemy 或 Coursera 等平台上开设与 Discourse 开发相关的课程的想法很有趣。我怀疑主要问题在于,除了 Discourse 团队之外,没有多少人有资格创建 Discourse 开发课程,而且课程的潜在学生数量相当少。话虽如此,我相信一门与开发 Discourse 主题或插件相关的优秀课程,随着时间的推移,可以获得足够多的学生,使其值得投入精力来创建。

另外一个可能的问题是,对 Discourse 课程收费可能违背本论坛的精神。不过我只是在猜测。

Discourse 开发教程

我认为关于许多 Discourse 插件、主题和主题组件的实际实现相当简单的观察是正确的。与其他平台的开发一样,问题在于如何克服不理解各部分如何协同工作的初始障碍。Discourse 团队(或其他合格的开发人员)可以通过编写一些教程来帮助解决这个问题,这些教程将引导你完成创建功能性主题、主题组件和插件的整个过程。例如,一个关于创建 Discourse 占位符主题组件的分步指南。

我意识到这需要大量的时间投入,因此需要与 Discourse 的业务目标保持一致。

当前可用资源

通过一点搜索,可以在本论坛上找到大量关于 Discourse 开发的优质信息。查看 Discourse GitHub 仓库中的代码示例也是一种很好的学习方式。

最近一个不应被忽视的工具是 GitHub Copilot。如果你以正确的方式构建开发环境,它可以帮助你了解如何开发 Discourse 主题和插件。对于开发 Discourse 主题,我发现的最佳方法是在本地 Discourse 安装的根目录中开发主题(使用 Discourse 主题 CLI)。这样构建可以使 Copilot 轻松访问 Discourse 代码库。(请注意,对于插件开发,plugins 文件夹已在根目录 /discourse 中。)(另外请注意,我可能错了,Copilot 实际上并没有访问我在 IDE 中加载的 Discourse 代码库。无论如何,核心 Discourse 代码可供我自己参考是有帮助的。)

为了避免分心,并专注于将 Copilot 用作学习工具,我在我的 IDE(VS Code)中关闭了 Copilot 的自动补全功能,只通过聊天与 Copilot 进行交互。以下是一个示例,说明它可以提供什么样的帮助。(shopify.js 是 Theme CLI 在我的主题的 /javascripts/discourse/api-initializers/ 目录中创建的文件。)

与 Copilot 的对话

scossar: 你能解释一下 shopify.js 中的默认导出在做什么吗?它基本上是使用 discourse_theme gem 创建主题时 Discourse 提供的样板代码。我已经修改了样板代码,以便它会记录每次页面更改。我理解 api.onPageChange 的调用,但我并不清楚 api 对象是如何被注入到我的代码中的。

GitHub Copilot: api 对象通过 apiInitializer 返回的对象中的 initialize 方法被注入到你的代码中。

以下是简化版的操作:

  1. 当 Discourse 启动时,它会运行所有初始化器。

  2. apiInitializer 函数创建一个在 "inject-objects" 初始化器之后运行的初始化器。

  3. 当此初始化器运行时,它会调用 withPluginApi 函数,并将 versioncbopts 参数传递进去。

  4. withPluginApi 函数会检查当前的 Discourse 版本是否与指定的版本兼容。如果兼容,它会调用回调函数 (cb) 并将 PluginApi 实例作为参数传递。这个 PluginApi 实例就是你在代码中看到的 api 对象。

因此,api 对象是 PluginApi 的一个实例,它通过 withPluginApi 函数传递到你的代码中。这个对象提供了许多允许你与 Discourse 交互的方法,例如你已经在使用的 onPageChange

scossar: 那么 shopify.js 中默认导出的第二个参数函数就是 apiInitializer 接受的回调函数吗?

GitHub Copilot: 是的,没错。apiInitializer 的第二个参数是一个回调函数。当初始化器运行时(假设当前的 Discourse 版本与指定的版本兼容),这个函数会以 PluginApi 实例作为参数被调用。这就是 api 对象在你的 shopify.js 文件中可用的方式。

在我弄清楚之后……

scossar: ……还有另一个想法,api.decorateCooked 是否可以用来注入一个托管在外部应用程序上的评分 iframe(例如,由我正在开发的 Shopify 应用托管)?

GitHub Copilot: 是的,你可以使用 api.decorateCooked 将 iframe 注入到帖子中。以下是一个大致的示例,说明你如何做到这一点:

api.decorateCooked($elem => {
  const postId = $elem.data('post-id');
  const iframe = document.createElement('iframe');
  iframe.src = `https://your-app.com/ratings?post_id=${postId}`;
  iframe.width = '100%';
  iframe.height = '200'; // 根据需要调整
  $elem.append(iframe);
}, { id: 'rating-iframe' });

在这个示例中,api.decorateCooked 用于将一个 iframe 追加到每个帖子。iframe 的源被设置为你的外部应用程序上的一个 URL,并将帖子 ID 作为查询参数包含在内。你需要将 'https://your-app.com/ratings' 替换为你评分页面的实际 URL。

请注意,这是一个简化的示例。你可能需要根据你的需求进行调整,并且绝对应该添加错误处理和其他必要的预防措施,以确保它能够正确且安全地工作。

目前还不能指望 Copilot 能够写出你所有的代码,但它是一个学习如何编写 Discourse 代码的绝佳工具。

我认为更少的类别和更少的层级对老年人来说会更容易。

除非你有大量的流量但只有很少人感兴趣,否则你可能不需要太多的类别。