Close and Go BackBack to Viget

Rails 3 Generators: Say Hello!

Ben Scofield
Ben Scofield, Former Staffer, February 25, 2010

Still with me after the last batch of ported generators? Well, I’ve got something new for you this time – and by new, I mean unseen by Rails 2.3.5-looking eyes. That’s right, it’s time to take a look at the generators that make their first appearance in Rails 3!

Model_Subclass

[rails3] > rails generate model_subclass ...
model_subclass is deprecated. Invoke model with --parent option instead.

Whoa! I’m not sure when the model_subclass generator was added to Rails, but I know it’s not present in 2.3.5. Is it just me, or does it seem a little … aggressive to deprecate something that hasn’t even been released in a stable version? Why not just get rid of it outright?

(Oh, and if you're wondering what it does, take a look at my quick explanation of the --parent option in the model generator.)

Stylesheets

[rails3] > rails generate stylesheets
      create  public/stylesheets/scaffold.css

The stylesheets generator is the simplest generator that Rails 3 provides. You know the standard stylesheet you get from generating a scaffold? (I know, I know, I haven’t covered the scaffold generators yet. Rest assured, they’re similar enough to the Rails 2 scaffolds in this respect.) All this does is copy that stylesheet into your application for you. Heck, even the session_migration generator has to add the current timestamp to the migration file name.

Generator

[rails3] > rails generate generator Shoulda
      create  lib/generators/shoulda
      create  lib/generators/shoulda/shoulda_generator.rb
      create  lib/generators/shoulda/USAGE
      create  lib/generators/shoulda/templates

OK, the other new generators in Rails 3 are kind of lame, but the generator generator rocks. All the modularity I’ve pointed to in the new generator setup? This is where it pays off.

When you run this generator, you get two files and a directory. USAGE is for documentation, and will be shown as part of the help text when your generator is run. The Ruby file that’s created (in this case, shoulda.rb) looks like this:

class ShouldaFrameworkGenerator < Rails::Generators::NamedBase
  def self.source_root
    @source_root ||= File.expand_path('../templates', __FILE__)
  end
end

Any generator that takes a named argument (like the model generator, as compared to the stylesheets one) inherits from Rails::Generators::NamedBase. The source_root class method tells your new generator where to look for its templates (and sub-generators, if you want to create them).

The templates directory is, naturally enough, where you put the templates your generator needs. These are just Erb files (so you can use Ruby to inject dynamic content), though they may end in .rb, .yml, or whatever other file extension your generator may need to create.

There is a single unique option for the generator generator:

Options:
  [--namespace]  # Namespace generator under lib/generators/name
                 # Default: true

I don’t know that it’s ever a great practice to set this to false; any time you have multiple custom generators in your lib, you’ll need that namespacing to avoid potential conflicts in the USAGE file and the templates directory.

Next Up

And that’s almost it for the tour! Coming up, we’ll take a look at the last two generators to cover: scaffold and scaffold_controller. After that, we’ll start to dig a little deeper. We’ll see how to take advantage of the modularity I’ve pointed out by swapping out frameworks (e.g., Shoulda for Test::Unit), and we’ll also explore details at the implementation level. See you next time!

blog comments powered by Disqus

We're the Developers

at Viget Labs. We write about web development trends, tips, best practices, industry events, and our projects — all with an emphasis on Ruby on Rails.

Contact Us

Have any questions, comments, ideas, or secrets to share? Let us know.


What is the third letter in apple?

Sorry, you need to have Javascript enabled to use this form. (Don't blame us, blame the spammers!) If you'd like to contact us, please visit our Contact page.