# Rails plugin generator

**URL:** https://meta.discourse.org/t/rails-plugin-generator/95907
**Category:** Announcements
**Created:** [August 29, 2018, 11:43am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907 "2018-08-29T11:43:01Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 29, 2018, 11:43am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/1 "2018-08-29T11:43:01Z")

</div>

⚠

Deprecated, use [GitHub - discourse/discourse-plugin-skeleton: Template for Discourse plugins · GitHub](https://github.com/discourse/discourse-plugin-skeleton) instead please.

* * *

This is a dev feature for our beloved plugin authors.

With this commit [DEV: rails generator to create plugin skeleton (#6332) · discourse/discourse@ef36fdf · GitHub](https://github.com/discourse/discourse/commit/ef36fdfb64a06b91503b5ad270daebda96d00201) you can now use rails generators to create plugins:

```plaintext
rails g plugin --help
rails g plugin DiscourseRacoon

```

This will create a complete discourse plugin skeleton in your plugins directory:

```plaintext
rails g plugin DiscourseRacoon --no-scheduled-job
      create plugins/discourse-racoon/README.md
      create plugins/discourse-racoon/LICENSE
      create plugins/discourse-racoon/plugin.rb
      create plugins/discourse-racoon/assets/stylesheets/common/discourse-racoon.scss
      create plugins/discourse-racoon/assets/javascripts/initializers/discourse-racoon.es6

```

It’s currently doing very few things #pr-welcome on this if you see things to improve or options to add.

@angus @joebuhlig Happy to hear your thoughts on this.

Thanks @david for pushing me to write this as a generator.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 29, 2018, 12:32pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/2 "2018-08-29T12:32:30Z")

</div>

goodness … almost like _ember cli_ … /gets coat 🕵️‍♂️😉

Joking aside, that’s not just a productivity boost, but a nice help for newbies too, thanks!

---

<div class="post-metadata">

### Author: ![eviltrout](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/eviltrout/32/5275_2.png) [@eviltrout](https://meta.discourse.org/u/eviltrout)
#### Post date: [August 29, 2018, 1:16pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/3 "2018-08-29T13:16:09Z")

</div>

I really ❤ this.

It might be worth going back through all our guides/tutorials and updating them to use this.

---

<div class="post-metadata">

### Author: ![dan](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/dan/32/101549_2.png) [@dan](https://meta.discourse.org/u/dan)
#### Post date: [August 29, 2018, 4:36pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/7 "2018-08-29T16:36:36Z")

</div>

Congratulations! It looks nice. 👍

I started something similar. I am glad that a plugin generator is finally available, hopefully it will motivate other people to write more plugins!

---

<div class="post-metadata">

### Author: ![tophee](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tophee/32/73406_2.png) [@tophee](https://meta.discourse.org/u/tophee)
#### Post date: [August 29, 2018, 6:49pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/8 "2018-08-29T18:49:06Z")

</div>

> [@merefield](#):
>
> a nice help for newbies too

Except that plugin newbies like myself have (almost) no clue what this machine does 🥴 I guess that’s not the kind of newbies you meant…

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [August 29, 2018, 8:21pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/9 "2018-08-29T20:21:29Z")

</div>

@tophee it’s not the easiest skill to pick up but I’ve started to hit my stride after a few false starts.

Take a look at:

> [@How can I make my own Discourse plugins?](https://meta.discourse.org/t/how-can-i-make-my-own-discourse-plugins/90032/2):
>
> I’ve only just started but here’s my ‘starter for 10’ to get you going: Read: [these](https://meta.discourse.org/t/beginners-guide-to-creating-discourse-plugins-part-1/30515)[this](https://meta.discourse.org/t/how-to-start-building-stuff-for-discourse-if-youre-newbie-like-myself/45954) Try and read the code on the simplest, [but popular plugins](https://meta.discourse.org/c/plugin/l/top/yearly) and see if you can understand what they are doing (this is not always easy, especially with the complexity of dealing with multiple files and the sometimes brutal functional brevity of javasctipt, but persevere) You need to learn: Lots of Javascript (look no further than @mpj’s [Fun Fun Function excellent & fun (!) videos](https://www.youtube.com/channel/UCO1cgjhGzsSYb1rsB4bFe4Q) (thanks man!)) Lots of …

The most important tip is this: have something you passionately want to build in/add … then you will climb the required mountains 😉

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [August 29, 2018, 10:59pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/10 "2018-08-29T22:59:18Z")

</div>

This is awesome 🙂 🎉

A few quick thoughts:

- You could add notes in the plugin.rb and the initializer to direct the author to discourse-specific methods they can use in each context. Something like

- On first blush I wondered whether it makes sense to create the module and engine out of the box. A number of plugins don’t need any new server methods. But on balance I think it makes sense, as it indicates the way to go about it, and there’s no harm in having an unused module.

- I reckon the `about` should be blank rather than `AWESOME_PLUGIN`.

- It’s cool that the url defaults to `github.com/${author}` however this was a little unexpected. Sometimes folks put their full name in that field and sometimes there are multiple authors (e.g. the polls plugin), which could make this problematic. Perhaps the CLI could explicitly ask for the author’s github username then use that for both the author and to generate the url.

Generally, how far do you want to go down the path of explicit direction / hand-holding?

If the goal is to make it easier for new plugin devs to find their feet, there are a number of other things we could add such as more notes or links to helpful meta topics, [examples of overriding existing Discourse methods](https://meta.discourse.org/t/tips-for-overriding-existing-discourse-methods-in-plugins/83389) and other common plugin patterns.

---

<div class="post-metadata">

### Author: ![Mittineague](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mittineague/32/114259_2.png) [@Mittineague](https://meta.discourse.org/u/Mittineague)
#### Post date: [August 30, 2018, 1:54am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/11 "2018-08-30T01:54:11Z")

</div>

There’s going to need to be an arbitrary “scope” for this. eg. always, optional but common, advanced rarely, etc.

I think heavily commented and URLs to “man” pages would be good.

I also think having config locale and spec / acceptance folders might encourage more plugin authors to l10n and write tests.

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 30, 2018, 9:09am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/12 "2018-08-30T09:09:42Z")

</div>

Thanks! I pinged you knowing you would have very good insights, not disappointed 😃

There’s indeed a decision to take between: skeleton or skeleton + help build your first plugin

Maybe we could have an option: “–beginner” on by default, which would add comments at multiple places?

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 30, 2018, 10:17am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/13 "2018-08-30T10:17:14Z")

</div>

Most of your comments should be addressed by:

[https://github.com/discourse/discourse/commit/d40d241e72905dc044f771af5989f3b56809b61d](https://github.com/discourse/discourse/commit/d40d241e72905dc044f771af5989f3b56809b61d)

[https://github.com/discourse/discourse/commit/acc96abe1a4abb16363fec75d0a2d7fd803a7f25](https://github.com/discourse/discourse/commit/acc96abe1a4abb16363fec75d0a2d7fd803a7f25)

---

<div class="post-metadata">

### Author: ![angus](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/angus/32/341715_2.png) [@angus](https://meta.discourse.org/u/angus)
#### Post date: [August 30, 2018, 11:51am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/14 "2018-08-30T11:51:49Z")

</div>

I was just testing a theory about the origin of [an issue](https://meta.discourse.org/t/question-answer-plugin/56032/141) in the elections and qa plugins, and needed to test some logic in isolation. Normally I would create a new plugin by hand to do this, but this time it was much easier using the plugin generator, just a single command. Useful already 🙂 Thanks.

I was getting a NameError though on initial load after generating a plugin (I had removed `tmp`). The plugin.rb includes an auto-generated `enabled_site_setting` out of the box, but the setting isn’t defined in `config/settings.yml`. If you add the setting, the error goes away. We’ll need to either remove the auto-generated enabled setting or add a config/settings.yml with the auto-generated enabled setting included by default.

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 30, 2018, 12:12pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/15 "2018-08-30T12:12:49Z")

</div>

Agreed.

Should be now correctly handled by:

[https://github.com/discourse/discourse/commit/90e67b671b6d8c33c2c0bd0817a4e064a01a05ca](https://github.com/discourse/discourse/commit/90e67b671b6d8c33c2c0bd0817a4e064a01a05ca)

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 30, 2018, 2:38pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/16 "2018-08-30T14:38:56Z")

</div>

This is adding support for controller/routes/spec/acceptance:

[https://github.com/discourse/discourse/commit/2dfb097dd94911676c99c71434be223b5af98410](https://github.com/discourse/discourse/commit/2dfb097dd94911676c99c71434be223b5af98410)

---

<div class="post-metadata">

### Author: ![joebuhlig](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/joebuhlig/32/193054_2.png) [@joebuhlig](https://meta.discourse.org/u/joebuhlig)
#### Post date: [August 30, 2018, 3:17pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/17 "2018-08-30T15:17:16Z")

</div>

😍 Absolutely love this, @j.jaffeux! I have a local templated plugin that I use for this exact purpose. I can create the git repo and then copy/paste the files into the directory to create the “Initial commit.” So I can easily see us using this heavily at ProCourse.

Notes about potential enhancements:

- Looks like you have MIT as the license that comes with this. Most of our plugins are license free since they are proprietary and private. The code is owned by the client. But we have a fair number of clients who choose to share their commissioned work with the world and as such we drop in a GNU GPL v2 license on the repo. It’s been a challenge nailing down a license to use for those, but the general thinking is that it should follow core. My ask here is whether or not it should allow us to choose a license to be included.

- Include license URL in `about` section? We do this as part of themes already. It would likely be a good thing to do the same for plugins and then link to the license on the `/admin/plugins` page.

- I have a tendency to build plugins using a dedicated `/my-plugin/lib/my-plugin/engine.rb` file with an associated `/config/routes.rb` file. The `plugin.rb` file is great for showing me where to start, but I use it as a collecting zone for the structure of the plugin. The actual logic is stored in the engine file. I’d love for this to allow a one liner that creates that structure automatically.

- I can see how this could evolve in the future as well. Maybe a way to standardize the way plugins are built. For example, from the plugin directory, `rails g plugin i18n en.js.my-plugin.my-localization-string`. But it could be used to add plugin settings, routes, jobs, etc… Not sure how much I would personally use this because I know these structures and how they work. But for those new to the system, it could lower the learning curve a bit.

- More flexible `about` section? We use the Author line as ProCourse for every new plugin as opposed to the GitHub username. We also make sure the URL of the plugin is a full URL and not a link to the GitHub profile. Maybe it’s just me, but it seems like you could take the Name sent to the generator and the GitHub username and assume the repo name matches the name of the plugin (lowercased and dasherized). But I could see that causing issues in some places as well.

- Local defaults? This may just be the nature of my business, but I find myself (or a team member) creating a new plugin structure two to four times a week, sometimes more. And we have a set structure for the `about` section that we use. It would be great if we could save some defaults locally that work every time without the need to answer the questions each run.

That’s my first run through it. I’ve run it a couple times and can already see it speeding up the process significantly. Thank you! 🤗

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [August 31, 2018, 10:33am UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/18 "2018-08-31T10:33:47Z")

</div>

Thx, great points. Could you send me (in PM if necessary) an example plugin demonstrating the above points please ?

---

<div class="post-metadata">

### Author: ![joebuhlig](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/joebuhlig/32/193054_2.png) [@joebuhlig](https://meta.discourse.org/u/joebuhlig)
#### Post date: [August 31, 2018, 1:20pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/19 "2018-08-31T13:20:59Z")

</div>

I just finished creating a public version of this. That way others can use it as well and I can share links to specifics since I realized there are some more points that I do.

[https://github.com/procourse/discourse-plugin-template](https://github.com/procourse/discourse-plugin-template)

- Whenever I add custom routes to a plugin, I always use a [Constraint](https://github.com/procourse/discourse-plugin-template/blob/master/lib/discourse_plugin_template_constraint.rb) that ties to the plugin enabled setting. This prevents the [routes from existing](https://github.com/procourse/discourse-plugin-template/blob/master/config/routes.rb#L4) unless the site setting is true. I wish I saw this more in plugins as custom routes shouldn’t be allowed just because the plugin is installed.

- This template includes a [Rails controller](https://github.com/procourse/discourse-plugin-template/blob/master/app/controllers/discourse-plugin-template/hello_controller.rb) and an [Ember route](https://github.com/procourse/discourse-plugin-template/blob/master/assets/javascripts/discourse/discourse-plugin-template-route-map.js.es6). These are only used in about half of the plugins I do, but it’s nice to have them there just so the structure already exists. I don’t know that this generator needs to include these pieces, but it’s helpful on my end.

- I always start my stylesheets with a [global class selector](https://github.com/procourse/discourse-plugin-template/blob/master/assets/stylesheets/discourse-plugin-template.scss). Every time I add HTML to the plugin, I start with a wrapper `div` with `class="discourse-plugin-template"`. That ensures that my styles only apply to my custom code. Sometimes I need to add CSS outside of that selector, but it seems like most cases don’t have that requirement.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [August 31, 2018, 2:01pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/20 "2018-08-31T14:01:25Z")

</div>

> [@joebuhlig](#):
>
> custom routes shouldn’t be allowed just because the plugin is installed

The ‘built-in’ method for this is to use `requires_plugin` in the plugin controller. I agree that this isn’t used as much as it should be though, even in official plugins. (Example [here](https://github.com/discourse/discourse/blob/a71fe16647c69db57aa47a40f94a3eb82176b79b/plugins/poll/plugin.rb#L211), defined [here](https://github.com/discourse/discourse/blob/2d961601922bb98cca90a0d5c9f25cd00f0fc333/app/controllers/application_controller.rb#L266))

---

<div class="post-metadata">

### Author: ![sivert](https://avatars.discourse-cdn.com/v4/letter/s/e495f1/32.png) [@sivert](https://meta.discourse.org/u/sivert)
#### Post date: [October 30, 2018, 5:45pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/21 "2018-10-30T17:45:42Z")

</div>

Just created a plugin with name “TrustLevelGroups” using plugin generator, after that can’t run server cause an error

 ![00%20AM](https://global.discourse-cdn.com/meta/original/3X/b/a/ba09685717c43a928dccf6eac6411585e43a5a19.png)

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [January 6, 2019, 3:22pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/22 "2019-01-06T15:22:11Z")

</div>

Out of the box I get a similar error

---

<div class="post-metadata">

### Author: ![j.jaffeux](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/j.jaffeux/32/60297_2.png) [@j.jaffeux](https://meta.discourse.org/u/j.jaffeux)
#### Post date: [January 6, 2019, 3:30pm UTC](https://meta.discourse.org/t/rails-plugin-generator/95907/23 "2019-01-06T15:30:08Z")

</div>

I have several fixes on my local branch… been using it a lot recently. Will push soon.

[Next page](https://meta.discourse.org/t/rails-plugin-generator/95907.md?page=2)
