This took me wayyy too long to figure out, so I figured I’d share an end to end guide. Shoutout to this GitHub gist.
Background
If you’re like me, you hate typing boilerplate so you use rails g scaffold Thing
. Oftentimes, we come up with design patterns that aren’t covered by the Rails default scaffold. To get around this, you can create custom generators.
Create a Generator
First, we’ll create our Something
generator. Note that this is namespaced under the Rails
module.
rails g generator rails/something
Now that you’ve generated it, fill out the resulting USAGE
and something_generator.rb
files like so.
Description:
Generates something
Example:
bin/rails generate something Thing
This will create:
app/something/thing.rb
class Rails::SomethingGenerator < Rails::Generators::NamedBase
source_root File.expand_path("templates", __dir__)
def create_something
file_path = "app/something/#{file_name}.rb"
create_file file_path, "# Oh hai there"
end
end
If you want to be extra fancy, you can create a template and spec! But I don’t feel like it so here we go.
Initializer
Next we need to create an initializer to hook into the scaffold generator. I called mine config/initializers/custom_scaffold_generators.rb
.
require "rails/railtie"
require "rails/generators"
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
module SomethingGenerator
module ScaffoldControllerGenerator
extend ActiveSupport::Concern
included do
hook_for :something, in: nil, default: true, type: :boolean
end
end
end
module ActiveModel
class Railtie < Rails::Railtie
generators do |app|
Rails::Generators.configure! app.config.generators
Rails::Generators::ScaffoldControllerGenerator.include SomethingGenerator::ScaffoldControllerGenerator
end
end
end
Note that we set it so default: true
, so it’s automatically included in the scaffold. Voila, you’ve got a working custom scaffold generator.
rails g scaffold Thing
invoke active_record
create db/migrate/20220618203059_create_things.rb
create app/models/thing.rb
... a bunch of stuff we don't care about in this post
invoke something
create app/something/thing.rb