Basic plugin template


(Paul Apostolos) #1

I need to create a plugin to implement some custom functionality for our forum. I have looked at a bunch of plugins on GitHub but I am wondering if there is a sort of template to follow.

It seems I just need a plugin.rb file and then a replication of the folder structure of Discourse for the files I want to replace or add included.

Is that right?

What is the purpose of the plugin.rb file? I am not going to be replacing or adding any javascript files only rb and erb files.

Actually, is that even possible with a plugin; replacing a core rb and erb file?


Allow reply-to individual instead of topic/forum (mailing list feature)
(Régis Hanol) #2

Have you read the plugin tutorials?


(Paul Apostolos) #3

Yep, I did…But I haven’t seen an example of replacing a .erb or .rb file.

All the examples seem to be surrounding javascript files.

I want to completely replace an erb file located in the /discourse/app/views/email folder with my own and override methods 1 and 3 in the following example .rb file.

class ExistingClass < SomeOtherClass::Base
	def method1(arg1, arg2)
		#body of method1
	end

	def method2(arg1)
		#body of method2
	end

	def method3(arg1, arg2)
		#body of method3
	end

	def prop1
		#body of property
	end
end

(Kane York) #4

With Ruby code, you can just start redefining the methods.

# file: plugin.rb
# Author: paully21

register_javascript 'my_js.js'

require 'email.rb'

class Email
  def existing!(arg1)

  end

  def self.some_variable
    5
  end
end

How can I override SiteSettings.min_post_length from a plugin for special topics?
(Paul Apostolos) #5

Okay…I’m slowly catching on.

A few more questions.

If I’m not using any JavaScript, I don’t need the register line, right?

Let’s say in Discourse (stock setup) the file email.rb already exists and it’s located in /discourse/app/models (it’s not, but let’s just say it is)…Do I need to do anything special with the file/folder structure of the plugin to make your code work?

If the plugin redefines the method and Discourse just calls the method as it normally would, how does it know to use my method instead (insert animated .gif of something to do with magic here)?

What about views, .erb files, with no class/methods definitions to override? How do I ensure those are included / used?

I think I can just use the new path to the template I want to use from my plugin and the root path will be

Rails.configuration.paths["plugins/myplugin"]

Correct?


(David Celis) #6

Right.

Nope, you should just be able to re-open the Ruby class and override methods

The old method is gone, since you redefined it on the Email class, which was already loaded into the Ruby process from the main Rails app. There can be only one! :wink:

I’ve been wondering this as well!


Show "topic-excerpt" for all post on Latest Page
(Avi Douglen) #7

Well, have you managed to figure that out yet? :slight_smile:

Also I was wondering about something else, in @riking’s sample code, the Email class override was right in the plugin.rb file. I would like to assume that I don’t need to put all my Ruby code in the single plugin file, right?
But then how does discourse know to load the other .rb files? Does it just go and load all .rb files in the directory?


(Kane York) #8

You’ll have to require them, which will follow normal Ruby path resolution.


(Avi Douglen) #9

Ah! So after the plugin.rb hook, from there on its just regular Ruby, with all the monkeypatching and method calls. Very cool, gives a lot of flexibility!

I didn’t see this mentioned anywhere, but is there a subset that is recommended for plugin use, or recommended to not touch? Or is it anything goes, just go learn the internal code structure…


(Kane York) #10

Yes, monkeypatching is fair game. Check out the code for discourse/docker_manager, which is the code for /admin/upgrade.

There are some methods that the plugin loading puts into scope for you. Among these are gem - if your plugin needs a gem - and register_asset and friends.


(SMHassanAlavi) #11

How can we add a function to be done on every page change and where should this function be defined?