Rails' batteries-included approach is one of its greatest assets. No other framework makes it so effortless to get your application off the ground quickly, at least partially due to Rails' generators.
If
you've used Rails for any amount of time, you have come across generators. Need to create a new application? Run rails new
. Need to scaffold a bunch of new models and views?
Run rails generate scaffold
. There are dozens more available to help you get
started rapidly or streamline your workflow.
But sometimes, using generators is just not enough. You might want to customize the behavior of these commands or even create your own. In this article, we'll take a closer look at generators - in particular, how to create your own custom Rails application using templates.
Let's get started!
What Are Rails Generators?
Not to be confused with generator functions (which you might be familiar with from Python or Javascript), Rails generators are custom Thor commands that focus on, well, generating things.
There are lots of examples. You'll likely be familiar with the model generator (rails generate model
) for creating
new ActiveRecord models or the migration generator (rails generate migration
) for generating new migrations. There is
also rails generate generator
which — you guessed it — creates a new generator!
Generators can call each other — for example, rails scaffold
will call numerous other generators — and provide
methods to create or modify files, install gems, run specific rake tasks, and much more. Let's create a
simple model spec generator to understand how this works.
Creating Your Own Generator in Ruby on Rails
Run the following:
This will create several new files in /lib/generators/model_spec
. We can modify model_spec_generator.rb
in folder lib/generators/model_spec/
to create a model spec file in the correct directory:
The template
command will look for a template file in the lib/generators/model_spec/templates
directory and render
it to the specified location — the spec/models
directory. The command will replace ERB-style variables
found in the template file.
By setting the source_root
, we let our generator know where it can find referenced template files. Template
model_spec.rb
in folder lib/generators/model_spec/templates/
could look like this:
Once you have created that file, you can run the generator to create a new spec file.
Many gems ship with generators such as this one. In fact, we created a simplified version of the generator Rspec ships with. FactoryBot has a generator for factories. There are many more examples.
The generators in various gems are more sophisticated than the one we created. We could
make our generator take arguments or even hook it into existing generators such as rails scaffold
. Refer to the Rails generators documentation if you want to learn more.
So generators have the potential to simplify your workflow in an existing application. But can we also use generators to customize setting up a new application?
Enter templates!
Templates in Ruby on Rails
As the name suggests, templates are files for customizing your application setup. Don't confuse these with the template files that we previously discussed! Under the hood, they are just generators with a specific purpose, as evidenced by the template API. While not exactly identical to generators, they are very similar.
If you have an existing template file, you can use it like so:
Rather than specifying a local file, you may also specify a URL. This is especially useful as it allows you to share application templates.
You are not limited to using templates when running rails new
either. If you've already set up an app, you can apply
templates afterward by executing:
Templates can be extremely useful. Who doesn't want to automate adding the same couple of gems and making the same configuration changes every time they create a new app? Creating your own application template is great fun — even if it doesn't save a lot of time in the long run.
Creating Your Own Template in Rails
We now know about generators and how to use templates. Let's create a simple application template to automate some setup steps.
How you set up your Rails app is very much down to personal preference, but here's an example:
- Install the dotenv gem.
- Create a
.env.development
file for the development environment. - Adapt the database configuration file to use environment variables.
- Optionally install and set up Rspec.
Let's create a local file — mytemplate.rb
— and add dotenv
using the gem
command.
As we've just added the dotenv gem, let's also create a .env.development
file to contain our database
configuration.
You can create a new file with specific content by using create_file
. You won't find this in the template or generator
documentation, as the method is supplied by Thor. You might also come across the alias file
. Application templates are
evaluated in the context of Rails::Generators::AppGenerator
, and that's exactly where the file
alias is defined.
The app_name
variable contains the first argument of rails new
. Using this variable, we can ensure our config file
matches the generated application.
Next, let's use our environment variables to connect to the database. We could overwrite the entire config/database.yml
using the create_file
command, but let's modify it instead using inject_into_file
.
We can use both strings or regex with the after
argument to specify where to inject content.
Of course, using this kind of configuration only makes sense if a user isn't creating an application with SQLite.
You can check for the presence of certain arguments by using the options
variable. It's best you read the source code of Rails' app generator to see which options are available.
Last but not least, let's also allow users to install Rspec if they want to. There are various
methods for taking user input and creating interactive templates. The yes?
method asks a user for
confirmation:
We already know the gem
method, but generate
and after_bundle
are new.
As mentioned before, Rspec adds its own generators, and you can call these generators (or any other ones, for that
matter) directly from your template. But there is a catch — gems specified with the gem
method are only installed at
the end of the template. Calling generate
with a generator supplied by such a gem would fail — which is why you should register
the command as a callback with after_bundle
.
Note: Before we wrap up, a quick word about creating or modifying files. We used create_file
and inject_into_file
,
but there are many other options. You may come across copy_file
or template
when reading different templates. I did not
mention them here to keep things simple. If you want to create more advanced templates, you
should know that these other methods for dealing with files exist.
The Result: The Final Template in Rails
The final template should look like this:
You can test this particular template by running:
Or:
To take advantage of the custom database configuration.
As mentioned, this file is perfectly suited to share as a GitHub gist. Adapt it to suit your needs, upload it, and then share it with your colleagues, friends, and anyone else interested in your custom app template 😉.
Learn More About Rails Generators and Templates
Needless to say, we've just scratched the surface here.
Everyone has different preferences for writing and developing Rails apps, so there are numerous generators and application templates out there. You can learn a lot about doing specific customizations by reading about them. I recommend Chris Oliver's Jumpstart and RailsBytes, the latter of which is a community-curated collection of templates.
There is also Thoughtbot's Suspenders, which inspired me to dig deeper into Rails generators and templates. I even wrote my own application template — Schienenzeppelin — which, while not up-to-date, might still provide some inspiration.
Wrap Up: Get Started with Ruby on Rails Generators and Templates
In this post, we looked into the basics of Rails generators and how they are used. We created our own generators to simplify writing new model specs.
We then delved into templates and learned how you could create a simple template to customize your application setup. This can be a bit of work, but also quite rewarding. If writing your own templates is not for you, there are many existing ones online to choose from!
Happy templating!
P.S. If you'd like to read Ruby Magic posts as soon as they get off the press, subscribe to our Ruby Magic newsletter and never miss a single post!