Saturday, November 3, 2007

The New Merb Generators

Update: The general information in this article is still correct, but the syntax is now nicer. You can read about the new syntax here.

In preparation for the big 0.4 release of Merb, the generators have had a major overhaul. Merb is ORM agnostic and uses plugins to harness an ORM. There are currently plugins for ActiveRecord, Sequel, and DataMapper.

The ORM agnostic goal of Merb, is a great thing, developers can use what they're comfortable with, or what suits a particular task at hand. This does create it's own issues of how to support it in the framework.

There's been great work done on merb to make this reasonably painless on selecting which ORM to use. Once the gem for the plugin is installed, a quick trip to config/dependencies.rb, and uncomment the line for your plugin and your away. But with generators it's been a bit more difficult up to now.

You'd think that will the option of ORM, and Rspec vs Test::Unit things could get a bit murky. Up to now the generators have been named specifically for the ORM you want to use so you can get the right syntax and parent classes etc. The only controller generator was just a blank stub that you have to fill out each time. Well now there's a new way to manage your generation needs.

Rubigen is awsome

DrNic extracted the generators from rails and added some of his magic to them. The result is a very clever and flexible system for generating files for your app and Merb tries it's hardest to put all this goodness to work for you.

Ok Already. Example Time

After you've installed the gem for your ORM plugin you need to tell Merb to use it for generators.
# config/merb_init.rb

# Put your selection for generators in here. I'll use DataMapper because I like it :)
Merb::GENERATOR_SCOPE = [:data_mapper, :merb, :rspec]
This will tell Merb to generate with Datamapper, and Rspec. This could have been :active_record and :test_unit if you want to go down that road. The order you put these in will matter in future (hopefully ;))

Generate A Model

ruby script/generate model my_model attr:type attr:type
This will generate the correct model, migration if required, and the correct test or spec stub. If you change the GENERATOR_SCOPE to use :active_record and generate another model, you'll see that the correct files are generated.
Note: This currently is not available when you're not using an ORM plugin. There are plans to allow this but at the moment it's not happening.

Generate Controllers

There are two ways to generate a controller.
  1. merb_controller
  2. resource_controller
The first, merb_controller just generates a blank controller stub, helper and tests or specs. This is available all the time, even when you're not using an ORM.

The other is available when you use an ORM plugin.
ruby script/generate resource_controller my_model
This generates a CRUD controller with the correct sytnax for your ORM selection you specified in merb_init.rb along with the helpers and test or spec stubs.

Currently there is no "resource" generator that takes care of a model and controller and all the associated files. This is on the drawing board and hopefully it won't take too long to get it sorted.

Change the ORM, mix and match your test_unit or rspec selections to see it in action. I wouldn't experiment by changing scopes in a real project though since Merb currently only supports using one ORM at a time.