Creating a generator for rails is simple enough.[1] You have to create a directory in lib or vendor and call it generators. Then you create ruby class (Name)Generator that extends Rails::Generator::NamedBase or Rails::Generator. You create a method called manifest that will do the actions to for your generator.
In the manifest you call record with a block. Somethings you can do in the block?
</pre>
<br><br>
Simple enough so lets script it! Thats right I created a generator to create generators. <br>
<pre>
sbecker@funtime-theme-park:~/rails/gens$ ruby script/generate generator test
create lib/generators/test
create lib/generators/test/templates
create lib/generators/test/templates/controllers
create lib/generators/test/templates/tests
create lib/generators/test/templates/views
create lib/generators/test/templates/models
create lib/generators/test/templates/helpers
create lib/generators/test/templates/libs
create lib/generators/test/USAGE
create lib/generators/test1/test_generator.rb
The script creates the correct file structure,the generator.rb file and the templates folder with some default folders. If you do not need all these folders then delete them. I think it helps keep to the templates grouped together.
To create the generator I have two templates and the manifest. The templates are for the USAGE file which is from the controller USAGE, and a basic manifest which has example calls that i listed above. The manifest for the generator is simple.
class GeneratorGenerator < Rails::Generator::NamedBase
attr_accessor :gen_path,:gen_name
def initialize(*runtime_args)
super(*runtime_args)
raise "You need a Generator name" if runtime_args.first.size<1
@gen_name=runtime_args.first.first
raise " You already have a generator called #{gen_name}" if File.directory?(RAILS_ROOT+"/lib/generators/#{gen_name.downcase}")
@actions = @args.empty? ? [] : Array(@args)
@gen_path=@gen_name.downcase
end
def manifest
record do |m|
m.directory File.join('lib','generators', gen_path)
m.directory File.join('lib','generators', gen_path,'templates')
m.directory File.join('lib','generators', gen_path,'templates','controllers')
m.directory File.join('lib','generators', gen_path,'templates','tests')
m.directory File.join('lib','generators', gen_path,'templates','views')
m.directory File.join('lib','generators', gen_path,'templates','models')
m.directory File.join('lib','generators', gen_path,'templates','helpers')
m.directory File.join('lib','generators', gen_path,'templates','libs')
m.template 'USAGE', File.join('lib', 'generators',gen_path,"USAGE")
m.template 'generator.rb', File.join('lib', 'generators',gen_path,"#{gen_name}_generator.rb")
end
end
end
I will add the generator code to my svn soon.
Useful sites:
[1]
http://wiki.rubyonrails.org/rails/pages/UnderstandingGenerators
[2]
http://www.aidanf.net/rails/creating-your-own-generators-in-railsI have posted about my ruby on rails generator that generates generators before. When I created this I did not know the generator code that well. Sadly this is still the case. I used generators for my one task saving me from created a nearly similar files over and over again. But Becker could you have not metaprogramed it? No each model had a common idea and interface but in the end the code was very different. I could have reduced the code and created a mixin for most of the methods, but it's a little late for that. Also I do not think I want to create a mixin for code that should be changing a lot.
Long story shorter I created some generators. I found my self creating another rails app for my websites and I am writing the login code over and over again. I thought why not generate? Then I thought why has someone not done this? But they
have and, each of the generators work. They all have good attributes and bad ones but, none of them are 100% what I wanted. So I am going to make my own login generator. I will post it in my svn when its ok. I also realize the literature on generators is lacking. I also feel that the amount of generators that have been created is very low. It might be the most under used feature in RoR.