August 19, 2008 03:21
Posted by Jeremy Durham
Creating generators in Merb 0.9.4
New Generators?
Last week I outlined a few of the things that I noticed had changed in Merb 0.9.4. Amongst the small list was one item that is particuarly interesting:
Generators seem to be packaged totally differently. I could be wrong because it’s just “at a glance”. Since I rely on a few plugins I’ve ported (paperclip, paperclip_polymorphs, acts-as-taggable-on), I need to get this one working soon.
So, today just so happens to be “soon”. Templater is very cool, and although I only use a few features, it was easy to convert an existing Rubigen generator to a Templater generator.
Sometimes magic is too magical
One thing that I personally disliked about Rubigen + Merb was that generators could not easily have no arguments. This was because the base Merb generator expected at least one argument, and so overriding this functionality easily involved duplicate a fair amount of code, which is never going to make a Ruby developer happy.
The generators were also a bit “magic”, in that the initialize method’s call to super did a few “magical” things to the passed in variables. You end up using lots of instance variables, many of which you did not create and have no idea how they got there.
But, this is about Templater, so let’s see about building a simple generator in a Merb plugin.
Less talk, more code
First, generate a simple Merb plugin:
merb-gen plugin first_generator
Now, add something similar to the following to your first_generator.rb inside your plugin:
Merb.add_generators(File.join(File.dirname(__FILE__), 'generators', 'first_generator'))
Now, you need to add a directory in lib called generators, and in there, a file named first_generator.rb, so that the above add_generator call will work.
Here is a very simple first_generator.rb:
module Merb::Generatorsclass FirstGenerator < NamespacedGeneratordesc <<-DESCFirst GeneratorDESCendadd :first, FirstGeneratorend
Now, you should be able to run merb-gen generators and see “first”. Well, that was easy. But that’s not why we’re here, right?
Templater has a nice DSL for writing generators, which makes the trivial tasks dead simple. So, let’s assume we want to accept two arguments. Inside of the FirstGenerator, you need to add the following:
first_argument :name, :required => true, :desc => "model name"second_argument :bacon, :required => true, :as => :boolean, :desc => "I'm hungry"
This will mean that two parameters are required, and the parameters can be accessed in the class as the locals “name” and “bacon”.
Now, what if we want ERB templates, a typical thing in a generator? With a bit more work, you can attach that ERB to a generated file in our app. Add this to the FirstGenerator class:
template :first dosource(File.dirname(__FILE__) / 'templates' / '%file_name%.rb')destination("app/models/#{name}_#{bacon}.rb")end
This will read the file file_name.rb in templates and local variables like name, bacon, and local methods inside of the FirstGenerator class will be in scope inside of this ERB template.
I found using Templater to be very easy, and significantly less work than using Rubigen, with much less code, which to me is a win all the way around.
There is a lot of functionality to Templater, but this should at least get you started converting from Rubigen to Templater.








