If you’ve used Rails at all then you’ll be familiar with Rails generators and will have used the script/generate command to create models, controllers, scaffolds and so on. The generators in Rails 3 have been rewritten and are completely different from those in Rails 2. For one thing they are now much more modular, which means that you can customize them to suit your preferences.

If we run rails g from the root directory of a Rails 3 application we’ll see a list of the generators available to that application. If we haven’t created any generators of our own then we’ll only see the generators that are included with Rails 3: controller, generator, helper, integration_test, mailer, metal, migration, model, observer, performance_test, plugin, resource, scaffold, scaffold_controller, session_migration and stylesheets. For the most part these generators behave the same way as their Rails 2 counterparts.

If we run a generator with the --help option it will show help information for that generator along with a list of options. If we try this with the scaffold generator we’ll see that there are a lot of options available and these options give us a lot of flexibility in customizing how the generator behaves.

Note that some of the options have default values. For example the --stylesheets option defaults to true. But what if we don’t want the stylesheets created when we generate a scaffold? Well, with a boolean option that defaults to true we can prefix the option with --no to disable that option. To demonstrate this we’ll create a new scaffold called project without a stylesheet.

If we look at the output from the command we’ll see that no stylesheet files were generated because we have disabled that option.

As well as the list of created files the output from running the generator shows a number of calls to invoke and these lines indicate where other generators are invoked. This means that the scaffold generator doesn’t do much work by itself, instead delegating to other generators such as the active_record generator which creates the model file and a migration. The active_record generator then calls another generator, test_unit, to create a unit test file and a fixture. This pattern is repeated further down with the scaffold_controller generator invoking the erb, test_unit and helper generators to create all of the files connected to the controller and its associated views. This makes the system very modular and means that we can replace pieces of it with other generators. If we want to use Haml instead of erb in the views, or Shoulda or RSpec instead of Test::Unit for testing we can plug these generators in instead.

Now that we know this we can look again at the list of options that the help for the scaffold generator again and they should begin to make more sense. For example the --orm option allows us to change the ORM that generates the models for us so that we could use DataMapper instead of the default ActiveRecord. Further down the options list is a list of ActiveRecord options that apply to the ActiveRecord version of the generator along with the options for the TestUnit and ScaffoldController generators.

Changing The Default Options

While it’s useful to be able to pass in options such as --no-stylesheets to generators it would be far more useful if we could change the default options and in Rails 3 we can do this on a per-application basis by modifying the application.rb file. The default application.rb file generated when we create an application has the following commented-out section in it.

If we uncomment this section we can override the default options for all of the generators in the application. The options that are provided as an example match the default options so we can replace them with our own. To make the stylesheets option false by default we can write:

/config/application.rb

# Configure generators values. Many other options are available, be sure to check the documentation.
config.generators do |g|
g.stylesheets falseend

If we run the help command for the scaffold generator again it will reflect the new defaults and the --stylesheets option will no longer be shown as having a default of true.

Next we’ll try something a little more adventurous and change the test framework to be Shoulda instead of Test::Unit and replace the fixtures with Factory Girl by changing the default fixture-replacement option.

To do this we first need to specify the relevant gems in the application’s Gemfile. We’ll only need these gems in the test environment so we’ll place them in a group.

/Gemfile

group :testdo
gem "shoulda"
gem "factory_girl"end

Unfortunately these two gems don’t include generators for Rails 3 but we can use another gem called rails3-generators that includes generators for a number of Rails 3 plugins and gems, including Factory Girl and Shoulda. We’ll add this gem to the Gemfile too, but only add it to the development group so that it’s only used in the development environment.

/Gemfile

gem "rails3-generators", :group => :development

That done we’ll need to run

terminal

bundle install

to install the gems. Once the gems have installed we can run rails g to see a list of the available generators. At the end of the list there should now be all of the generators that are created by the rails3-generators gem.

Now that we have these new generators we can modify the generator configuration in application.rb and add the defaults we want for the test_framework and fixture_replacement options.

At the top of the output we’ll see that the shoulda and factory_girl generators were invoked correctly but that further down the scaffold_controller generator couldn’t find a shoulda generator for erb or for the helper file. If we look at the list of helpers again we can see that we only have shoulda generators for models and controllers.

terminal

$ rails g
...
Shoulda:
shoulda:controller
shoulda:model

What should we do here? Well, if we look at the Rails Guides page for generators we’ll see that it’s possible to add fallback generators so that if a certain generator isn’t found a different one will be used. All we need to do is modify the config block in application.rb again.

Let’s say that we want to remove the line break tag at the end of the template and wrap the link at the bottom in a paragraph element instead. How can we change the template so that every generated index view is customized that way?

To do this we can create new custom templates within a new templates directory under the application’s lib directory. The generators will look here for template files before using the defaults. In order to determine which template to override we’ll have to take a look at the Rails source code. The code for the generators is held in the railties/lib/rails/generators directory and the default view templates are in a erb/scaffold/templates/ directory under that. We can copy the contents of the index.html.erb file in this directory and customize it to suit our needs.

We need to create a similar directory structure underneath the generators directory and so our customized index template needs to be at /lib/templates/erb/scaffold/index.html.erb. We can then paste in the default template file and change it to suit. Once we’ve done that if we create a new scaffold, say for a model called Category, then we’ll see the index view based on our custom template.