Building a custom Stimulus generator for Rails30 Nov 2020
If you’ve spent any time working with Ruby on Rails, you know that using generators can save you from a lot of console commands and copy/pasting from one file to the next. Need a new model? Just run
rails g model MyNewModel name:string description:string and you’re set.
Rails covers most of the common use cases for you with built-in generators. If the built-in generators don’t meet your needs, you can get fancy by creating your own custom generators. Custom generators can save you time any time you’re finding yourself running lots of touch commands and copy/pasting boilerplate into new files.
Despite its growing popularity, Rails does not provide a generator out of the box (as of Rails 6.0). Without a generator, every new Stimulus controller requires a manual
Today we’re going to solve this problem by learning how to build our own custom generator for Rails. Our custom generator will create new a new Stimulus controller in the
rails g stimulus ControllerName.
Let’s get started.
I’m writing this assuming that you have a Rails 6 project and you’re working from that project in your terminal.
If you don’t have a Rails project handy, just run
rails new stimulus_generator_project and then
cd stimulus_generator_project to follow along.
Generating a generator
Rails is known for valuing developer experience, and Rails generators are a prime example of that love for developers. Rails provides a ton of generators out-of-the-box including a generator to generate new generators. Very meta stuff, and very convenient for us.
We’ll use the generator generator to generate a new Stimulus generator. Still with me? Great. Run this in your console and let’s move on from generating generators:
This applies Rails magic to create the bones of our generator, named
stimulus, in the lib directory. You’ll notice that inside of the
lib/generators/stimulus directory there are a few files and an empty
templates directory. We’ll briefly talk about what each of these items is and then we’ll create our generator.
stimulus_generator.rb: This is the file that runs when you type
rails g stimulus in your console. The class defined here will manage creating a new file each time the generator runs, and populating that file with the content from our template Stimulus controller.
USAGE: This file contains instructions for users of your generator. The contents of this file are printed when you type
rails g stimulus in your console.
Templates: The templates directory contains any files that your generator will copy when it runs. In our case, we’ll just have one file. These template files can access and insert variables into the template, when needed.
stimulus_generator_test.rb: The generator generator helpfully creates a test file, which can be run (in our case) with
rake test. Our generator is simple, but we’ll add a test to make sure it works as we expect.
Adding our code
As a reminder, we’re building a generator to create a new Stimulus controller. This generator will only accept a name as an argument and will always create the controller in the
Let’s first add a test to our
stimulus_generator_test file. We’ll use this test to make sure our generator works without having to generator a Stimulus controller we don’t want.
lib/generators/stimulus/stimulus_generator_test.rb add a test that runs our generator and validates that a new file is generated as expected:
When we run rake test the test will fail, which is expected since our generator hasn’t been built yet. Let’s work on making it pass.
First, create the template file that our generator will copy each time it runs. This file will live in the templates directory:
In this new file, we’ll insert the content of our Stimulus controller:
My template includes the basic structure of a Stimulus controller plus the lifecycle methods I find myself using most often, that’s what makes the most sense to me. You can include more lifecycle methods or just leave out everything but the class definition, you’re the boss of your own template file.
With our template file created, we can go into our generator file and tie the generator and template together:
Each time rails g stimulus Something is called, any method in this file will run. In our case, we just create a new file from our template using the template method (provided by Thor, if you’re interested in the inner workings of Rails generators). If we want to handle conflicting file names, make our file name generation smarter, process additional arguments or otherwise make our generator more powerful we can add additional methods to do so. For our purposes, we will keep things simple.
With our template and our generator class built, let’s see if our tests pass:
Perfect! We’ve got a working generator and we can run that generator with
rails g stimulus CoolIdea.
If you’ve followed along with me through this tutorial, when we run the generator our new controller will be created at
Congratulations on making it this far! You’re a star.
Our last step is to update the
USAGE file for our generator with useful information for others who encounter our generator in the future. Something like this will work fine:
Now when we run
rails g stimulus our help text will be printed to the terminal. The generator is pretty simple today, but in the future we might add additional arguments or options. Starting with documentation from day one is always the better plan.
Today we learned how we can use the magic of Rails to create our own generators and we used that knowledge to fill a gap in the Rails defaults by creating a simple generator to add new Stimulus controllers.
While our example was simple, the same technique can be applied to create sophisticated new generators for Service Objects, complex Stimulus controllers, or any other resource you find yourself needing. In addition to creating our own custom generators, we can also use this knowledge to change the default generators provided by Rails. Overriding the default model or controller generators can help your organization enforce code standards across an organization or just save you from copying boilerplate across your project.
For more reading on the power of Rails generators, start with the Rails guide on generators. Finally, if creating your own Stimulus generator isn’t a chore you’re looking forward to, I’ve published a gem you can use to add Stimulus generator just like the one in this tutorial to your Rails projects.
Thanks for reading!