1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Refactored some generators to make use of improved invocations on thor.

This commit is contained in:
José Valim 2009-07-15 11:33:36 +02:00
parent a06c825b46
commit 0702e04e0d
15 changed files with 95 additions and 67 deletions

View file

@ -83,7 +83,7 @@ task :create_rails do
require File.join(File.dirname(__FILE__), 'lib', 'generators')
require 'generators/rails/app/app_generator'
Rails::Generators::AppGenerator.start [ File.basename(PKG_DESTINATION), "--quiet" ],
:root => File.expand_path(File.dirname(PKG_DESTINATION))
:destination_root => File.expand_path(File.dirname(PKG_DESTINATION))
end
# Copy Vendors ----------------------------------------------------------------------------

View file

@ -6,15 +6,15 @@ module Rails
end
class Base < Thor::Group
include Rails::Generators::Actions
include Thor::Actions
# Automatically sets the source root based on the class name.
#
def self.source_root
@_rails_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates'))
File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates'))
end
include Thor::Actions
include Rails::Generators::Actions
# Tries to get the description from a USAGE file one folder above the source
# root otherwise uses a default description.
#

View file

@ -3,22 +3,21 @@ module Rails
class GeneratorGenerator < NamedBase
check_class_collision :suffix => "Generator"
def copy_generator_file
template "generator.rb", generator_dir("#{file_name}_generator.rb")
end
class_option :namespace, :type => :boolean, :default => true,
:desc => "Namespace generator under lib/generators/name"
def copy_usage_file
template "USAGE", generator_dir("USAGE")
end
def create_templates_dir
empty_directory generator_dir("templates")
def craete_generator_files
directory '.', generator_dir
end
protected
def generator_dir(join)
File.join("lib", "generators", file_name, join)
def generator_dir
if options[:namespace]
File.join("lib", "generators", file_name)
else
File.join("lib", "generators")
end
end
end

View file

@ -1,8 +0,0 @@
Description:
Explain the generator
Example:
./script/generate <%= file_name %> Thing
This will create:
what/will/it/create

View file

@ -1,5 +0,0 @@
class <%= class_name %>Generator < Rails::Generators::NamedBase
def self.source_root
@source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
end
end

View file

@ -1,12 +1,11 @@
require 'generators/rails/generator/generator_generator'
module Rails
module Generators
class PluginGenerator < NamedBase
class_option :tasks, :type => :boolean, :aliases => "-t", :default => false,
:desc => "When supplied creates tasks base files."
class_option :generator, :type => :boolean, :aliases => "-g", :default => false,
:desc => "When supplied creates generator base files."
check_class_collision
def create_root_files
@ -17,16 +16,21 @@ module Rails
directory 'lib', plugin_dir('lib'), false # non-recursive
end
hook_for :test_framework
def create_tasks_files
return unless options[:tasks]
directory 'tasks', plugin_dir('tasks')
end
def create_generator_files
return unless options[:generator]
directory 'lib/generators', plugin_dir('lib/generators')
hook_for :generator, :aliases => "-g", :type => :boolean do |instance, generator|
instance.inside_with_padding instance.send(:plugin_dir) do
instance.invoke generator, [ instance.name ], :namespace => false
end
end
hook_for :test_framework do |instance, test_framework|
instance.inside_with_padding instance.send(:plugin_dir) do
instance.invoke test_framework
end
end
protected

View file

@ -6,7 +6,7 @@ module TestUnit
check_class_collision :suffix => "Test"
def create_test_files
directory 'test', "vendor/plugins/#{file_name}/test"
directory '.', 'test'
end
end
end

View file

@ -5,17 +5,13 @@ Dir[File.join(File.dirname(__FILE__), "actions", "*.rb")].each do |action|
end
class Thor
# Some actions require that a class method called source root is defined in
# the class. Remember to always cache the source root value, because Ruby
# __FILE__ always return the relative path, which may lead to mistakes if you
# are calling an action inside the "inside(path)" method.
#
module Actions
attr_accessor :behavior
# On inclusion, add some options to base.
#
def self.included(base) #:nodoc:
base.extend ClassMethods
return unless base.respond_to?(:class_option)
base.class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
@ -31,6 +27,50 @@ class Thor
:desc => "Supress status output"
end
module ClassMethods
# Hold source paths used by Thor::Actions.
#
def source_paths
@source_paths ||= from_superclass(:source_paths, [])
end
# On inheritance, add source root to source paths so dynamic source_root
# (that depends on the class name, for example) are cached properly.
#
def inherited(base) #:nodoc:
super
base.source_paths
if base.respond_to?(:source_root) && !base.source_paths.include?(base.source_root)
base.source_paths.unshift(base.source_root)
end
end
# Deal with source root cache in source_paths. source_paths in the
# inheritance chain are tricky to implement because:
#
# 1) We have to ensure that paths from the parent class appears later in
# the source paths array.
#
# 2) Whenever source_root is added, it has to be cached because __FILE__
# in ruby returns relative locations.
#
# 3) If someone wants to add source paths dinamically, added paths have
# to come before the source root.
#
# This method basically check if source root was added and put it between
# the inherited paths and the user added paths.
#
def singleton_method_added(method) #:nodoc:
if method == :source_root
inherited_paths = from_superclass(:source_paths, [])
self.source_paths.reject!{ |path| inherited_paths.include?(path) }
self.source_paths.push(*self.source_root)
self.source_paths.concat(inherited_paths)
end
end
end
# Extends initializer to add more configuration options.
#
# ==== Configuration
@ -88,14 +128,13 @@ class Thor
remove_dot ? (path[2..-1] || '') : path
end
# Receives a file or directory and serach for it in the source paths. Paths
# added for last are the one searched first.
# Receives a file or directory and search for it in the source paths.
#
def find_in_source_paths(file)
relative_root = relative_to_original_destination_root(destination_root, false)
source_file = nil
self.class.source_paths.reverse_each do |source|
self.class.source_paths.each do |source|
source_file = File.expand_path(file, File.join(source, relative_root))
return source_file if File.exists?(source_file)
end
@ -123,6 +162,15 @@ class Thor
@destination_stack.pop
end
# Same as inside, but log status and use padding.
#
def inside_with_padding(dir='', log_status=true, &block)
say_status :inside, dir, log_status
shell.padding += 1
inside(dir, &block)
shell.padding -= 1
end
# Goes to the root and execute the given block.
#
def in_root

View file

@ -37,15 +37,17 @@ class Thor
parse_options = self.class.class_options
options = if options.is_a?(Array)
if options.is_a?(Array)
task_options = config.delete(:task_options) # hook for start
parse_options = parse_options.merge(task_options) if task_options
Thor::Options.parse(parse_options, options)
array_options, hash_options = options, {}
else
Thor::Options.parse(parse_options, []).merge(options)
array_options, hash_options = [], options
end
self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).freeze
options = Thor::Options.parse(parse_options, array_options)
self.options = Thor::CoreExt::HashWithIndifferentAccess.new(options).merge!(hash_options)
self.options.freeze
end
class << self
@ -81,10 +83,6 @@ class Thor
file = caller[1].match(/(.*):\d+/)[1]
Thor::Base.subclasses << klass unless Thor::Base.subclasses.include?(klass)
if klass.respond_to?(:source_root) && !klass.source_paths.include?(klass.source_root)
klass.source_paths.unshift(klass.source_root)
end
file_subclasses = Thor::Base.subclass_files[File.expand_path(file)]
file_subclasses << klass unless file_subclasses.include?(klass)
end
@ -341,13 +339,6 @@ class Thor
end
end
# Hold source paths used by Thor::Actions. Paths added for last are the
# one searched first.
#
def source_paths
@source_paths ||= []
end
# Default way to start generators from the command line.
#
def start(given_args=ARGV, config={}) #:nodoc:

View file

@ -12,19 +12,18 @@ $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../../activerecord/lib"
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
require 'generators'
CURRENT_PATH = File.expand_path(Dir.pwd)
class GeneratorsTestCase < Test::Unit::TestCase
include FileUtils
def self.test_dir
@@test_dir = File.expand_path("#{File.dirname(__FILE__)}/../../")
end
def destination_root
@destination_root ||= File.join(self.class.test_dir, 'fixtures', 'tmp')
@destination_root ||= File.expand_path(File.join(File.dirname(__FILE__),
'..', '..', 'fixtures', 'tmp'))
end
def setup
cd self.class.test_dir
cd CURRENT_PATH
rm_rf(destination_root)
mkdir_p(destination_root)
end