Wilson E. Husin

Overriding tailwindcss-rails generators

November 19, 2022 (UTC)

I like using TailwindCSS and Rails. However, many times I want to make a change on the default generator, such that rails generate scaffold conform to the theme of the rest of the application.

Unfortunately, that option isn’t available (yet).

Reverse-engineering from the setup that made tailwindcss-rails gem take control of scaffolding, I managed to find a quick and dirty solution. Let’s walk through it.

How does Rails know anyway? ¶

In the GitHub pull request where tailwindcss-rails creates Tailwind-friendly scaffold templates, it identifies itself to Rails with the following:

# lib/tailwindcss/engine.rb

Rails.application.config.app_generators do |g|
  g.template_engine :tailwindcss
end

This means the engine can be customized. Specifically, this line is overriding the scaffold_controller generator.

Let’s override it! ¶

In this example, I chose “internal” as the name of my application-specific generator. Create a file under config/initializers/. I have generators.rb for all generator-related configuration, but you can name it anything.

# config/initializers/generators.rb

require_relative "../../lib/generators/internal"

Rails.application.config.app_generators do |g|
  g.template_engine :internal
end

Time to draw the rest of the owl.

# lib/generators/internal.rb

module Internal
end

require_relative "./internal/scaffold/scaffold_generator"

Now, within scaffold/, it’s pretty much copying-over what tailwindcss-rails has defined in lib/generators/tailwindcss/scaffold/. Here is a one-liner shell to do that.

mkdir -p lib/generators/internal/scaffold/
cp -r \
  $(bundle info tailwindcss-rails --path)/lib/generators/tailwindcss/scaffold/* \
  lib/generators/internal/scaffold/

Remember to rename the module from Tailwindcss to match the module defined above.

# lib/generators/internal/scaffold/scaffold_generator.rb

require "rails/generators/erb/scaffold/scaffold_generator"
require "rails/generators/resource_helpers"

module Internal  # This is the line you'd need to replace.
  module Generators

The rest of customization is unsurprisingly plain Ruby. Go nuts!