嘿,抱歉问这个新手问题。我一直在阅读文档,但还是需要一些指导。
我 fork 了 Discourse 并进行了自己的修改,希望基于这些修改进行自己的部署。贡献指南介绍了如何进行修改并提交 PR,但在这个场景中,我并不想提交 PR。我只是希望基于我的微小修改,让 Discourse 能够正常安装运行。我原以为方法是将这一行指向我自己的仓库:
我这样做了并执行了安装,但我的修改并没有生效,显然我哪里做错了。有什么建议吗?谢谢!
编辑:
为了透明起见,也以防有人有更简单的方法,我实际上只是想允许匿名用户在进入匿名模式时更改他们的用户名。这很简单,只需将这一行中的 false 改为 true:
如果有更好的方法,我非常乐意听取。但目前我只需要启用这个功能。我擅长 Python、Java 以及许多其他后端技术,但对 Ruby/JavaScript/HTML 等几乎一无所知。
编辑 2:
根据我在其他地方看到的一篇帖子,我按以下方式更新了 app.yml:
run:
- exec:
cd: /var/www/discourse
cmd:
- sudo -u discourse git remote set-url origin https://github.com/my/forked/discourse.git
- sudo -u discourse git fetch origin
- sudo -u discourse git checkout origin/master
重新构建应用后仍然没有效果。应用可以正常启动,但我的修改似乎并未生效。
pfaffman
(Jay Pfaffman)
3
所有这样做的人都后悔莫及,而且在这里你也很难得到帮助。
无论你打算做什么,请通过插件来实现。
10 个赞
neounix
(Dark Matter)
5
嘿 @leighno5
就我个人经验而言,我的想法是:如果你已经足够了解 Ruby 和 Rails,能够轻松地为 Discourse 编写插件(或修改任何 Rails 类),那么通过插件来实现你在“分支”中所做的事情会容易得多。
如果我们还不足以轻松理解 Rails 和 Ruby 并编写 Discourse 插件,那么我的经验是:直接 Fork 并修改核心代码是“误入歧途”的。
我想打个比方(抱歉这个想法很简单):
“有人觉得走路很困难,于是决定直接去跑步。”
如果不介意的话,让我解释一下:
在我开始编写 Rails 应用(与 Discourse 无关)并尝试编写 Discourse 插件之前,我有点迷茫,甚至对 Discourse 有些恼火。这就像第一次打高尔夫球:球不会直线飞行,需要大量练习才能将球打到球道中央。Fork 并修改 Discourse 核心,就像在你还不会用短铁杆切球和推杆之前,就直接在练习场拿出大号开球木杆!
我曾暂时停止对 Discourse 的“黑客式”修改(那是几个月前的事了),转而实际从零开始构建了一些 Rails 应用。之后(也只有在那之后),我才开始对 Rails 建立起某种“直觉性”的理解。从那以后,当我决定修改 Discourse 时(目前我已在生产环境中运行了自己编写的 6 个自定义插件),一切都变得直观起来,那些需要修改 Ruby 核心的插件也变得过于简单。
Ruby 非常灵活。我们可以覆盖任何类、任何对象,甚至可以重新定义 Ruby 的每一个方面。随着经验的积累,我们会开始感叹:“哇!我完全没想到 Ruby 如此灵活(而且强大)!”然后开始“变得危险”,因为我们能像超人一样在 Ruby 和 Rails 中自由翱翔。那时,我们才刚刚踏上 Ruby 和 Rails 的旅程,远未到终点!
凭借我在 2020 年积累的 Ruby 和 Rails 知识,如果现在让我重来,我绝不会像你所提议的那样去 Fork Discourse 并修改 Ruby 和 Rails 核心。因为一旦我们理解了 Ruby 类的基础以及元编程的基本概念,通过插件来覆盖和修改 Ruby 类简直太容易了。
我想表达的意思是(抱歉如此直接):如果有人认为必须通过修改 Discourse 核心来实现一些微小的 Ruby 改动,那说明他们对 Ruby 和 Rails 的理解还不够深入;因为如果他们真的理解了,就不会去修改核心,而是会直接编写一个简单的插件来覆盖类,并享受“猴子补丁”(monkey-patching)的乐趣。
另一方面,如果我想做一些疯狂的事情,比如用 React 和 Ant Design 替换 Discourse 的 EmberJS,让自己陷入痛苦,那么 Fork 确实是唯一可行的途径!然而,在我看来,“Discourse”并非由“JavaScript 库”定义。Discourse 是由核心开发团队(这些人)的技能、他们对细节的关注、客户服务、开源代码开发的团队协作方式、他们的 SPA 功能管线以及他们所有的辛勤工作所定义的!仅仅因为可能更喜欢 Ant Design(配合 React)或 VueJS 而不是 Ember,就抛弃所有这些智慧,在我看来有点疯狂。
如果我们只是打算对 Discourse 核心进行零星的修改,这一点更是如此!为了这种目的去 Fork 它,抛弃那些真正的“人”(他们才是“真正的”Discourse,而非代码),未免有点“疯了”。
以上只是我 2020 年学习 Ruby 和 Rails 的个人经历。现在,基础部分已经变得容易,我也开始“变得危险”了,哈哈。我可以“随意进行猴子补丁”,但这并不总是好事;而这正是 Discourse 插件存在的意义。
保持核心坚如磐石,尽情通过插件在 Discourse 上“折腾”吧。
希望这能帮到你。
顺便一提,在写这条回复时,你写道:
这某种程度上证明了我的观点,你不觉得吗?
在 Discourse 中编写“插件”,从某个层面来说就是编写"Ruby 代码”;而对其他人来说,这还涉及更深层的内容(比如 EmberJS)。
在你开始编写 Discourse 插件之前,我的友好建议(虽然对你来说可能显得毫无价值)是:先开发一些 Ruby on Rails 应用。至少掌握 Ruby 和 Rails 的基础知识,之后,你自然会回答自己上面提出的问题。
今天早上,我和客户开了三个小时的电话会议,讨论一个 Rails 应用、验证、模型等内容。会议结束后,我稍作休息,编写了一些会议中确定的待办事项,然后读到了你的帖子。
在我看来,编写 Discourse 插件的最短路径,就是先学习 Rails。
希望这能帮到你!
5 个赞
不,您完全正确。我完全没有 Ruby 经验,所以绝对没有冒犯之意!
我已经看过插件指南,并反复阅读了几遍,但遗憾的是,我对 Ruby 的无知仍然让我感到沮丧。我完全不知道该如何编写一个插件,来覆盖 user-guardian 文件中的那部分代码,以允许匿名用户更改他们的用户名。
2 个赞
neounix
(Dark Matter)
8
你好 @leighno5
是的,我理解你的情况。
那些“如何操作”(HOWTO)类的插件主题是由非常有才华的开发者撰写的,他们拥有超过十年的 Rails 和 Ruby 编程经验(甚至可能更长)。事实上,其中一些人可以说是全球顶尖的 Ruby 和 JavaScript 开发者之一。
我百分之百确定,这些开发者在编写他们的第一个 Discourse 插件之前,早就已经学习了 Rails 和 Ruby。
学习 Rails 其实并没有那么难;但你确实需要亲身实践“动手仪式”,从零开始构建几个 Rails 应用程序。不仅仅是跟着 YouTube 教程走(这当然很好),而是要真正构建一个可运行的应用程序,在其中你必须处理数据库设置、生成自己的模型、生成自己的控制器、编写模型验证、编写初始化脚本、编写辅助模块、进行数据库迁移(修改)、使用嵌入式 Ruby 等等。
这其实非常有趣,也是让你真正感到有信心编写插件的“最短路径”(就 Rails 方面而言,我个人并不太涉及 Ember,但我非常喜欢 Rails 这一侧的工作!)。
此外,你还必须掌握 Rails 控制台!Rails 控制台真的很有趣,我每天都很愉快地使用它!
今天,我和我最喜欢的客户通过 AnyDesk 协作,他问:“我们能不能看看这个新的库存视图?”他想看着我现场完成整个过程。当我们把它搭建并运行起来后,通话结束时他说:“你在 Rails 中用 30 分钟完成的事情,几十年前可能需要花费数周时间!!”真是太棒了,@leighno5。加油吧!!
当你学会 Rails 之后,你会发现编写 Discourse 插件其实相当简单,至少就 Rails 和 Ruby 部分而言是这样!!
希望这对你有帮助(HTH)。
3 个赞
查看现有的 #plugin 代码。现在这类代码非常多,有大量的示例可供参考。切勿跳过对既有成果的阅读,以便充分利用它们。
听起来你只是想覆盖一个方法,这只需在你的 plugin.rb 中重新定义该方法即可(尽管最佳实践 arguably 是将每个模块拆分为独立文件,但仅针对一个方法而言,这样做并不值得)。
5 个赞
冒着进一步暴露我的无知并滥用您已给予的善意的风险,您是否愿意对此稍作展开说明?或者,如果您知道其他有人覆盖模块的示例并能提供链接,我将不胜感激。我完全不反对“阅读手册”(rtfm),但尽管我花了很多时间浏览各种教程和文档,我对 Discourse 工作原理的缺乏理解仍然让我感到沮丧。是的,我知道这类基础问题会让人觉得我投入甚少,但我保证事实并非如此!
3 个赞
这是我们在 PostGuardian 中定义了一个方法的示例:
你可以对 UserGuardian 采用类似的做法,使用现有的方法名,这样应该会覆盖原有实现。
简单方案(用于快速实现,但不够稳健):
直接复制原始方法的代码并进行你的修改。缺点是:如果 Discourse 更新了代码,你的插件可能会导致实例出错。
高级方案(更稳健的解决方案):
为了更进一步,你可以尝试使用 super 来继承原始方法,但这并不保证一定能成功(原因这里就不详细展开了)。不过,这仍是最佳实践,因为这样 Discourse 对该方法的任何更新都会被自动考虑,而无需你手动修改插件代码。
Discourse 是一个平台,需要时间来熟悉。请一步一步来。
6 个赞
这正是我所担心的。你下一段中提到的“高级方法”在操作指南中有涵盖吗?是否有现成插件中使用的、简单且良好的示例,可供在创建新插件时参考(或复制)?
目前不必担心高级方法,先确保它能正常运行。你可以在线指南的其他部分研究 Ruby on Rails 的一般知识。这超出了 Discourse 具体内容和本论坛的范围,请知悉。
1 个赞
好的,谢谢!假设我抽空写了一个小型插件。如果我没理解错的话,每次升级时,我都应该检查核心代码,并在相关核心代码发生变化时重写该插件。是这样吗?谢谢。
1 个赞
没错。只需偶尔检查一下,尤其是在它开始出现故障时。由于 Guardian 代码涉及站点授权,因此更为关键,请密切关注。
另一种解决方案是添加测试用例(即 specs),并设置自动化任务来运行它们……但这会变得更加复杂!
2 个赞
pfaffman
(Jay Pfaffman)
16
另一个额外加分任务是设置 travis-ci.org 来运行你的插件测试,这样一旦插件出现问题,你就能及时收到通知。
5 个赞
这显然不是一项可以掉以轻心的任务。我想修改登录/创建新账户的模态框,并移除 Twitter 图片。或许后者是更合适的首要项目。谢谢。
如果任何人遇到此问题,且曾像我一样感到迷茫,我将提供我的代码,因为它已按预期运行。我没有修改任何文件,只需创建一个新文件 plugin.rb,并将以下内容放入其中:
# name: noms
# about: 允许匿名模式下的用户更改其用户名
# version: 0.1
require_dependency 'guardian'
require_dependency 'guardian/user_guardian'
class ::Guardian
end
module ::UserGuardian
def can_edit_username?(user)
return false if SiteSetting.sso_overrides_username?
return true if is_staff?
return false if SiteSetting.username_change_period <= 0
return true if is_anonymous?
is_me?(user) && ((user.post_count + user.topic_count) == 0 || user.created_at > SiteSetting.username_change_period.days.ago)
end
def can_edit_name?(user)
return false unless SiteSetting.enable_names?
return false if SiteSetting.sso_overrides_name?
return true if is_staff?
return true if is_anonymous?
can_edit?(user)
end
end
这会覆盖 Discourse 核心中的 user_guardian.rb 类,从而允许用户更改其匿名用户账户的用户名和名称。
如果你将我提供的代码与 Discourse 核心中的 user_guardian.rb 进行对比,你会发现其中还有很多其他内容,我无需对其进行任何修改,因此保持原样。我只需要修改 can_edit_username 和 can_edit_name 这两个方法,将某些返回值从 false 改为 true,即可实现所需功能。
当然,这仍有改进空间,也可能存在最佳实践,这些可以通过阅读此处及其他地方的相关帖子来了解。但如果你像我一样是 Ruby 新手,只想对核心功能进行一些非常简单的调整,那么这是一个极简且可工作的示例,展示了你需要做什么。
非常感谢本线程中的各位对我的耐心、鼓励与帮助!特别感谢 @merefield,他过去曾帮助过我另一个帖子。
10 个赞
neounix
(Dark Matter)
19
哈哈
为了完成这些简单的任务,你们已经从最初打算分叉整个 Discourse 并放弃主分支的想法,走了很远的路。
干得漂亮 
4 个赞
你是按照 Install Discourse on Ubuntu or Debian for Development 的完整路径进行的,还是直接在您的生产站点上操作并听天由命?