Read more

How to create Rails Generators (Rails 3 and above)

Dominik Schöler
April 30, 2014Software engineer at makandra GmbH

General

Programatically invoke Rails generators
: Require the generator, instantiate it and invoke it (because generators are Thor::Groups, you need to invoke them with invoke_all). Example:

    require 'generators/wheelie/haml/haml_generator'
    Generators::HamlGenerator.new('argument').invoke_all
Illustration money motivation

Opscomplete powered by makandra brand

Save money by migrating from AWS to our fully managed hosting in Germany.

  • Trusted by over 100 customers
  • Ready to use with Ruby, Node.js, PHP
  • Proactive management by operations experts
Read more Show archive.org snapshot

Other ways: Rails invokes its generators with Rails::Generators.invoke ARGV.shift, ARGV. From inside a Rails generator, you may call the inherited Thor method invoke(args=[], options={}, config={}) Show archive.org snapshot . There also is a generate method which will run the generator in a subprocess. Call it with generate 'generator_name', 'command line args'.

Expected (hard-coded) directory structure of a generator

#{generator namespace, e.g. rails}/
  #{generator name, e.g. model}/
    templates/
      ...
    #{generator name, e.g. model}_generator.rb
    USAGE

Templates

If you want to use the supplied template, directory and other template methods, you must call source_root 'path/to/templates' inside your generator. If you stick to the expected directory structure, this will do it:

source_root File.expand_path('../templates', __FILE__)

To overwrite existing files, add the :force option: template 'config/database.yml', force: true

Hooks

Controller generators

Rails ships with a ResourceHelpers Show archive.org snapshot module. Require 'rails/generators/active_model' and include Rails::Generators::ResourceHelpers inside your generator class to have some helpers at hand, i.e. controller_class_name and controller_file_name.

Configuration

Rails generator templates are customizable. Their default template comes with the railties gem, but a custom template will be preferred. Put it here:

#{Rails.root}/
   lib/
     templates/
       #{generator namespace, e.g. rails}/
         #{generator name, e.g. model}/
           #{template name, e.g. model.rb}

Notes

generator namespace

Some generators invoke other generators: rails:model calls active_record:model by default (depending on the selected ORM). Thus, the model template is looked for in lib/templates/active_record/model/model.rb.

template name

Should be the same as the generator name, but actually depends on the generator's implementation.

Generator output

To announce what you are doing in your generator, you can use the method say_status. Statuses used by Rails are:

say_status :run, 'bundle install'
say_status :identical, :blue, 'some_file'
say_status :remove, :green, 'some_file'
say_status :create, :green, 'some_file'
say_status :skip, :yellow
say_status :conflict, :red

Note that standard methods like template are already calling say_status.

General caveats

Heads up when defining a class_option :attributes

Rails::Generators::NamedBase#initialize will automatically parse attributes into Rails::Generators::GeneratedAttributes.

Dominik Schöler
April 30, 2014Software engineer at makandra GmbH
Posted by Dominik Schöler to makandra dev (2014-04-30 18:37)