@merefield @fzngagan @muhlisbc Ok, so there are a variety of different ways to modify Discourse server modules and classes.
I’ve been considering all of this recently for the Multilingual plugin and now thinking about them when looking at @muhlisbc’s additions to the Question Answer plugin: https://github.com/paviliondev/discourse-question-answer/pull/30/files.
Interested in any of your thoughts on the below.
The goals
The goals with such modifications are to:
-
Allow the modification to be disabled via the enabled / disabled setting.
-
Default to the core functionlity as far as possible.
-
Make them as clear and simple as possible (i.e. plugin structure)
The approaches
There are only really two approaches that come close to fulfilling these goals, the server plugin api and module prepending.
Server plugin api
The methods in https://github.com/discourse/discourse/blob/master/lib/plugin/instance.rb are the Discourse server plugin api.
The upsides of this approach are that:
-
it’s supported by the Discourse team; and
-
it’s subject to the enabled setting
The downsides of this approach are:
-
it doesn’t allow you to refer to the super method (i.e. the method you’re overriding).
-
In larger plugins it leads to a long plugin.rb file that’s hard to follow.
Module prepending
Module prepending is described in some detail here: https://meta.discourse.org/t/tips-for-overriding-existing-discourse-methods-in-plugins/83389.
The upsides of this approach are:
-
It allows for modifications to be broken into distinct modules and put in seperate files for a clearer structure
-
It allows reference to the super method, to preserve core functionality as needed.
The downsides of this approach are:
-
It’s not supported by the Discourse team
-
It’s not automatically subject to the plugin enabled setting
This second downside can be overcome however by putting the module prepension in the plugin.rb file, and then making it subject to the plugin enabled setting.
Module prepension, subject to the plugin-enabled setting is currently my preferred approach.
Approaches to avoid
I would note that these other approaches should be avoided, as they either are unreliable ways to modify classes (i.e. don’t work in all situations in which the code might be called), are messy structurally, and / or don’t allow for use of the core code.
-
Class or module eval
Post.class_eval do def method end end
-
Aliasing methods, e.g.
class Post alias_method :method_old, :method end
-
Simply overdding a method by making a new declaration
class Post def method end end