When I try to find a guide about how to write rails generator, I can’t find a good one. So I decide wrote one.
Though Rails 3 will come, but I think people will keep using rails 2 for a long period.
Before we start you need know what is generator, rails provide many generator for us. You can type script/generate in your RAILS_ROOT.
You will find there is rails builtin: controller, helper, integration_test, mailer, metal, migration, model, observer, performance_test, plugin, resource, scaffold, session_migration
I think the must familiar with some of these.
Write your own generator is very simple, let me show you.
Assuming we will create a hello generator
1. create folder lib/generators/hello
2. create a ruby file lib/generators/hello/hello_generator.rb
class HelloGenerator < Rails::Generator::Base
def manifest # this method is default entrance of generator
puts "hello"
end
end
3.run script/generate hello, we print “hello”.
It is not enough, we need other function, like create folder, create file according to some template, copy file etc.
Rails is powerful. It support some basic command. I’ll show you one by one.
1. create folder, copy file
class HelloGenerator < Rails::Generator::Base
def manifest # this method is default entrance of generator
record do |m| #Convenience method for generator subclasses to record a manifest.
m.directory File.join("app","view","hello")
m.file "relative_source","relative_destination"
end
end
end
2. create file according to template
class HelloGenerator < Rails::Generator::Base
def manifest # this method is default entrance of generator
record do |m| #Convenience method for generator subclasses to record a manifest.
m.directory File.join("app","view","hello")
m.template "hello",File.join("app","view","hello","hello.html.erb")
end
end
end
template is locate at your generator folder templates sub folder.
For the example above, we create hello.html.erb according to hello template.
hello template acctually is a erb file. you can put some ruby code there.
for example
<ul>
<% 3.times do |i| %>
<li><%= i%> times
</li>
<% end %>
</ul>
After we know that, we do some fancy stuff, we can pass in some argument when we generate file.
Think how we generate controller using rails builtin generator.
script/generate controller controller_name action1 action2
we can do the same think. But how we get the argument in generator?
Assuming we call our generator using script/generate hello china world
we can get argument in generator from attribute args
class HelloGenerator < Rails::Generator::Base
def manifest # this method is default entrance of generator
record do |m| #Convenience method for generator subclasses to record a manifest.
puts args.inspect # ["china","world"]
m.directory File.join("app","view","hello")
args.each do |word|
m.template "hello",File.join("app","view","hello","#{word}.html.erb")
end
end
end
end
3. How we pass variable to template file?
class HelloGenerator < Rails::Generator::Base
def manifest
record do |m|
m.template "hello",File.join("app","view","hello","hello.html.erb"),:assigns => {:var1 => "var1",:var2 => "var2"}
end
end
end
OK, this is magic time. call this command script/destroy hello china world
See rails delete the resource we created using generator. Even if we didn’t write any extra code for it.
4. how we know it’s create or destroy, you can get it from options[:command]
class HelloGenerator < Rails::Generator::Base
def manifest # this method is default entrance of generator
record do |m| #Convenience method for generator subclasses to record a manifest.
puts options[:command]
end
end
end
More command rails generator support see http://api.rubyonrails.org/classes/Rails/Generator/Commands/Create.html
Next part I will introduce another generator Named Generator.
like how we create scaffold script/generate scaffold user name:string age:integer