Skip to content

Instantly share code, notes, and snippets.

@jnicklas
Created April 28, 2009 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jnicklas/103003 to your computer and use it in GitHub Desktop.
Save jnicklas/103003 to your computer and use it in GitHub Desktop.
# A suggestion for an improved DSL for templater. The idea is to unify a lot of concepts and make
# them simpler.
#
# * Options and arguments are unified into 'argument', that can have an optional position
# * Templates, Files, EmptyDirectories, Directories and Invocations are unified into Recipes
# * A use_recipe function which can be used to pick and choose certain recipes
# * A simple block syntax for opening up generators and adding stuff to them
#
Rails.generator(:model) do
# We can provide modules with some helpful functionality for building common types of generators
# A very nice way of doing this, since it's flexible and doesn't depend on load order.
# The end user of the generator will never see this, as it happens inside the framework
include Rails::Generators::BaseGenerator
include Rails::Generators::NamedGenerator
## ARGUMENTS
# this argument is required and it can be given as a positional argument
# the generator could be invoked like this:
# script/generate model --name User
# script/generate model User
argument :name do |arg|
arg.position = 0
arg.description = "Name of the generator"
arg.required = true
arg.validate do |name|
name !~ /\s/
end
arg.filter do |name|
name.camel_case
end
end
# this argument is not required and it cannot be given as a positional argument
# script/generate model --name User --no-migration
argument :no_migration do |arg|
arg.boolean = true
end
## RECIPES
recipe :model do
template "app/models/%file_name%.rb" # will copy the template, interpolationg %file_name% into the destination
end
recipe :spec do
directory 'spec' # will add all files in the directory 'spec' as templates
end
use_recipe :spec, :if => { :test_framework => :rspec }
recipe :test_unit do
template "test/models/model_test.rb", "test/models/#{file_name}_test.rb"
end
use_recipe :test_unit, :if => { :test_framework => :test_unit }
recipe :monkey do
template "test/monkey.rb"
end
use_recipe :monkey, false # do not use the monkey recipe
use_recipe :monkey, true # no, we changed our minds, use it!
use_recipe :monkey, :unless => { :monkey => 'Peter' } # use monkey recipe unless #monkey returns 'Peter'
use_recipe :monkey, :unless => :peter? # use monkey recipe unless #peter? returns true
recipe :migration do
generate :migration, "add_#{file_name}", :table_name => file_name.pluralize
end
use_recipe :migration, :unless => :no_migration?
recipe :add_route, :revertable => false do
append_text "\n\n resources :#{name}\n", :after => "Merb::Router.prepare do", :to => 'config/routes.rb'
end
## METHODS
# this is just a class so we can happily add methods to it
def monkey
"Peter"
end
def peter?
monkey == "Peter"
end
def file_name
name.snake_case
end
def class_name
name.camel_case
end
end
# We can use it like this in our code.
Rais.generator(:model).generate!(:name => "User", :recipes => [:model, :spec])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment