One of the most underrated features of Rails is its Generators. We use Generators in Rails all the time, every time we create a model, a controller, or a migration, we’re using Generators.
In most of our Rails apps, we may have a lot of code that we need to write repetitively.
NO! I’m not talking about reusable code that we can DRY out.
I’m talking about the logic that has already been extracted out to a module or a DSL method that needs to be added.
But did you know?, you can customize Rails Generators? You can! This is where Thor templates come into play.
Thor Templates are files(.tt extension) that are used to automate the process of generating code. Rails Generators are built on top of Thor.
By creating our own Thor Templates, we can customize Rails Generators.
Creating a Thor Template
Our custom templates will reside under
Creating our custom templates is easy.
In this post, I’ll show two use cases for customizing Generators by creating our Templates.
Customizing ActiveRecord Model Template
Let’s assume we have a Rails app and we have a requirement that every Models (with few exceptions) should have the following features:
- It should be searchable
- It should be auditable
- It should be able to retain its data even when deleted (Soft Deletable)
For these requirements, we have installed and integrated the following gems:
We now have the following logic in most of our models:
Now, we need to make sure these are added to every new model that we create in our app moving forward.
Let’s now create a custom template that helps us achieve this.
Let’s create a model.rb.tt file in
And add the following code:
This template now ensures that every new model that we create will have the required features and we don’t need to add them manually.
So now if we run the following command:
We’ll get the following output:
Now we can remove the name validation (since we don’t have a name attribute) and
FIXME comments and we’re good to go.
Customizing Rails Migrations
In the above template, we have added a name validation as a common requirement for all models.
This means we are expecting a name attribute in all our models.
Let’s customize our migration template to add a name attribute to all our models.
We’ll create a create_table_migration.rb.tt file in
Inside this file, we’ll add the following code:
Here, we have added a
t.string :name, null: false line so that it generates a name attribute in all our models.
The rest of the code ensures all other attributes are generated as it normally does.
Now, let’s generate a new model and see the migration file:
The migration now has a name attribute added to it.
Observe that we didn’t specify it in the generator command, it was generated automatically by the template.
Now we can just remove the FIXME comment and run the migration.
It makes a lot of sense to use custom generator templates if we have a lot of repetitive code in our app.
It saves us a lot of time and effort and makes our life easier.
There are other uses of templates that I have not covered in this post.
Adding a few references below for further reading: