This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
commit cb7a7dc4bdec96858b1c6ee2b37839d88fd24e23
tree 31ffe2610db06a6d3752d695db65eb451c2454a0
parent cd83247a0dee0a37ba263eda84ec0521dfb1b2ea
tree 31ffe2610db06a6d3752d695db65eb451c2454a0
parent cd83247a0dee0a37ba263eda84ec0521dfb1b2ea
README
= Templater
Templater is a system for generating files. Templater has the ability to both copy files from A to B and also to render
templates using ERB. Templater consists of four parts:
- Actions (Files and Templates)
- Generators
- Manifolds
- The command line interface
Each manifold has many generator, and each generator has many actions.
== Example
This is how to create a very simple system for generating things:
module MyGenerators
extend Templater::Manifold
class BlogGenerator < Templater::Generator
def self.source_root
File.join(File.dirname(__FILE__), 'templates')
end
template :blog, 'blog.rb'
file :me, 'me.jpg'
end
class WikiGenerator < Templater::Generator
def self.source_root
File.join(File.dirname(__FILE__), 'templates')
end
template :wiki, 'wiki.rb'
file :img, 'wiki.jpg'
end
add :blog, BlogGenerator
add :wiki, WikiGenerator
end
MyGenerators.run_cli Dir.pwd, 'my_generators', '0.1', ARGV
The generator classes override the source_root method to specify where templates will be located. All subclasses of
Templater::Generator that have any actions must do this. The +template+ and +file+ methods add actions to the generator.
In the first case, a template that is rendered with ERB and then put in its destination location, in the other case a
file that is copied.
The generators are added to the manifold, and assigned the names 'wiki' and 'blog'.
Neither manifolds or generators actually do anything by themselves, they are just abstract represenations. The last line
invokes the command-line-interface, which fetches the desired generator, tells it to render its templates and checks
with the user if there are any problems. The generators can easily be used without the command-line-interface, so it is
easy to construct an alternative interface.
== Invoking other generators
Generators can invoke other generators, a WikiBlog generator that creates both a Wiki and a Blog could look like this:
module MyGenerators
extend Templater::Manifold
class WikiBlogGenerator < Templater::Generator
invoke :wiki
invoke :blog
end
add :wiki_blog, WikiBlogGenerator
end
It needs to source_root, since it has no actions. Not here that the generators are invoked by their name in the
manifold, *not* by their class name. This gives the system a great deal of flexibility.
== Automatically adding actions
It can get tedious to declare each action, instead you can search in a given directory and automatically add all files
to your generator, this is done with the glob! function.
class MyGenerator < Templater::Generator
def self.source_root
File.join(File.dirname(__FILE__), 'templates')
end
glob!
end
This will search the source root and add all files as actions.
== Templates
There are a lot of ways of adding templates:
template :one_argument, 'source_and_destination.rb'
template :two_arguments, 'source.rb', 'destination.rb'
template :block do
source('source.rb')
destination(some_instance_method)
end
template :expression, 'source.rb' '%some_instance_method%.rb'
In the last example, the characters enclosed in percentage signs will be replaced with the results of the instance
method +some_instance_method+
Inside the templates normal ERB can be used. The templates are rendered in the same context as the generator instance,
so generator instance methods can be called from inside the template.
<% if name %>
puts "My name is <%= name %>"
<% else %>
puts "I have no name"
<% end %>
IF you need to render templates where the result should contain actual erb, simply use a double percentage sign, this
will prevent the statement from being executed.
<%= 2 + 2 %>
<%%= 2 + 2 %>
will result in
4
<%= 2 + 2 %>
== An advanced example
A generator for creating a model class, such as it used by Merb or Rails, could look like this:
module Merb::Generators
class ModelGenerator < ComponentGenerator
def self.source_root
File.join(super, 'model')
end
desc <<-DESC
This is a model generator
DESC
option :testing_framework, :desc => 'Specify which testing framework to use (spec, test_unit)'
option :orm, :desc => 'Specify which Object-Relation Mapper to use (none, activerecord, datamapper, sequel)'
first_argument :name, :required => true
second_argument :attributes, :as => :hash, :default => {}
invoke :migration do |generator|
generator.new(destination_root, options.merge(:model => true), name, attributes)
end
template :model, :orm => :none do
source('model.rbt')
destination('app/models/' + file_name + '.rb')
end
template :model_activerecord, :orm => :activerecord do
source('model_activerecord.rbt')
destination('app/models/' + file_name + '.rb')
end
template :model_datamapper, :orm => :datamapper do
source('model_datamapper.rbt')
destination('app/models/' + file_name + '.rb')
end
template :model_sequel, :orm => :sequel do
source('model_sequel.rbt')
destination('app/models/' + file_name + '.rb')
end
template :spec, :testing_framework => :rspec do
source('spec.rbt')
destination('spec/models/' + file_name + '_spec.rb')
end
template :test_unit, :testing_framework => :test_unit do
source('test_unit.rbt')
destination('test/models/' + file_name + '_test.rb')
end
def class_name
self.name.camel_case
end
def test_class_name
self.class_name + "Test"
end
def file_name
self.name.snake_case
end
end
add :model, ModelGenerator
end








