Discourse plugins 开发 复写 Controller function,以 module prepend 方式实现

基于不想修改 discourse 内核代码的需求,这样可以比较方便的持续更新最新版本以及一些安全修复,以插件模式开发是比较切合的,但是有些功能的实现需要对原生的方法进行修改,或者仅靠前端的逻辑不够,可以利用 module 的方式来 hook 内置的 function

举个例子,比如我们需要在用户 post 的时候做判断,discourse 调用了

PostsController 下面的 create 方法,比如我想在用户提交之前做判断,那么在 plugins.rb 中添加如下代码:

after_initialize do
  module CreateExtensions
    def create
      
      Rails.logger.info 'check before post'
      if {condition}
      	render json: {action: "create_post", errors: ["the reason why user can't post"]}, status: 422
      else
        super
      end
    end
  end

  class ::PostsController
    prepend CreateExtensions
  end

如果条件不符合,就返回一个 json,之后 discourse 会弹出一个提示框,这里的内容支持 html,也就是说可以添加 a 标签之类的富文本去引导用户跳转。如果条件符合,那么 super 会直接交还给原来的 create 方法,也就是 prepend 的实现。

参考 https://meta.discourse.org/t/tips-for-overriding-existing-discourse-methods-in-plugins/83389