aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails_generator/lookup.rb
diff options
context:
space:
mode:
Diffstat (limited to 'railties/lib/rails_generator/lookup.rb')
-rw-r--r--railties/lib/rails_generator/lookup.rb249
1 files changed, 0 insertions, 249 deletions
diff --git a/railties/lib/rails_generator/lookup.rb b/railties/lib/rails_generator/lookup.rb
deleted file mode 100644
index a3525364a2..0000000000
--- a/railties/lib/rails_generator/lookup.rb
+++ /dev/null
@@ -1,249 +0,0 @@
-require 'pathname'
-
-require File.dirname(__FILE__) + '/spec'
-
-class Object
- class << self
- # Lookup missing generators using const_missing. This allows any
- # generator to reference another without having to know its location:
- # RubyGems, ~/.rails/generators, and RAILS_ROOT/generators.
- def lookup_missing_generator(class_id)
- if md = /(.+)Generator$/.match(class_id.to_s)
- name = md.captures.first.demodulize.underscore
- Rails::Generator::Base.lookup(name).klass
- else
- const_missing_before_generators(class_id)
- end
- end
-
- unless respond_to?(:const_missing_before_generators)
- alias_method :const_missing_before_generators, :const_missing
- alias_method :const_missing, :lookup_missing_generator
- end
- end
-end
-
-# User home directory lookup adapted from RubyGems.
-def Dir.user_home
- if ENV['HOME']
- ENV['HOME']
- elsif ENV['USERPROFILE']
- ENV['USERPROFILE']
- elsif ENV['HOMEDRIVE'] and ENV['HOMEPATH']
- "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
- else
- File.expand_path '~'
- end
-end
-
-
-module Rails
- module Generator
-
- # Generator lookup is managed by a list of sources which return specs
- # describing where to find and how to create generators. This module
- # provides class methods for manipulating the source list and looking up
- # generator specs, and an #instance wrapper for quickly instantiating
- # generators by name.
- #
- # A spec is not a generator: it's a description of where to find
- # the generator and how to create it. A source is anything that
- # yields generators from #each. PathSource and GemGeneratorSource are provided.
- module Lookup
- def self.included(base)
- base.extend(ClassMethods)
- base.use_component_sources!
- end
-
- # Convenience method to instantiate another generator.
- def instance(generator_name, args, runtime_options = {})
- self.class.instance(generator_name, args, runtime_options)
- end
-
- module ClassMethods
- # The list of sources where we look, in order, for generators.
- def sources
- read_inheritable_attribute(:sources) or use_component_sources!
- end
-
- # Add a source to the end of the list.
- def append_sources(*args)
- sources.concat(args.flatten)
- invalidate_cache!
- end
-
- # Add a source to the beginning of the list.
- def prepend_sources(*args)
- write_inheritable_array(:sources, args.flatten + sources)
- invalidate_cache!
- end
-
- # Reset the source list.
- def reset_sources
- write_inheritable_attribute(:sources, [])
- invalidate_cache!
- end
-
- # Use application generators (app, ?).
- def use_application_sources!
- reset_sources
- sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/applications")
- end
-
- # Use component generators (model, controller, etc).
- # 1. Rails application. If RAILS_ROOT is defined we know we're
- # generating in the context of a Rails application, so search
- # RAILS_ROOT/generators.
- # 2. Look in plugins, either for generators/ or rails_generators/
- # directories within each plugin
- # 3. User home directory. Search ~/.rails/generators.
- # 4. RubyGems. Search for gems named *_generator, and look for
- # generators within any RubyGem's
- # /rails_generators/<generator_name>_generator.rb file.
- # 5. Builtins. Model, controller, mailer, scaffold, and so on.
- def use_component_sources!
- reset_sources
- if defined? ::RAILS_ROOT
- sources << PathSource.new(:lib, "#{::RAILS_ROOT}/lib/generators")
- sources << PathSource.new(:vendor, "#{::RAILS_ROOT}/vendor/generators")
- Rails.configuration.plugin_paths.each do |path|
- relative_path = Pathname.new(File.expand_path(path)).relative_path_from(Pathname.new(::RAILS_ROOT))
- sources << PathSource.new(:"plugins (#{relative_path})", "#{path}/*/**/{,rails_}generators")
- end
- end
- sources << PathSource.new(:user, "#{Dir.user_home}/.rails/generators")
- if Object.const_defined?(:Gem)
- sources << GemGeneratorSource.new
- sources << GemPathSource.new
- end
- sources << PathSource.new(:builtin, "#{File.dirname(__FILE__)}/generators/components")
- end
-
- # Lookup knows how to find generators' Specs from a list of Sources.
- # Searches the sources, in order, for the first matching name.
- def lookup(generator_name)
- @found ||= {}
- generator_name = generator_name.to_s.downcase
- @found[generator_name] ||= cache.find { |spec| spec.name == generator_name }
- unless @found[generator_name]
- chars = generator_name.scan(/./).map{|c|"#{c}.*?"}
- rx = /^#{chars}$/
- gns = cache.select{|spec| spec.name =~ rx }
- @found[generator_name] ||= gns.first if gns.length == 1
- raise GeneratorError, "Pattern '#{generator_name}' matches more than one generator: #{gns.map{|sp|sp.name}.join(', ')}" if gns.length > 1
- end
- @found[generator_name] or raise GeneratorError, "Couldn't find '#{generator_name}' generator"
- end
-
- # Convenience method to lookup and instantiate a generator.
- def instance(generator_name, args = [], runtime_options = {})
- lookup(generator_name).klass.new(args, full_options(runtime_options))
- end
-
- private
- # Lookup and cache every generator from the source list.
- def cache
- @cache ||= sources.inject([]) { |cache, source| cache + source.to_a }
- end
-
- # Clear the cache whenever the source list changes.
- def invalidate_cache!
- @cache = nil
- end
- end
- end
-
- # Sources enumerate (yield from #each) generator specs which describe
- # where to find and how to create generators. Enumerable is mixed in so,
- # for example, source.collect will retrieve every generator.
- # Sources may be assigned a label to distinguish them.
- class Source
- include Enumerable
-
- attr_reader :label
- def initialize(label)
- @label = label
- end
-
- # The each method must be implemented in subclasses.
- # The base implementation raises an error.
- def each
- raise NotImplementedError
- end
-
- # Return a convenient sorted list of all generator names.
- def names
- map { |spec| spec.name }.sort
- end
- end
-
-
- # PathSource looks for generators in a filesystem directory.
- class PathSource < Source
- attr_reader :path
-
- def initialize(label, path)
- super label
- @path = path
- end
-
- # Yield each eligible subdirectory.
- def each
- Dir["#{path}/[a-z]*"].each do |dir|
- if File.directory?(dir)
- yield Spec.new(File.basename(dir), dir, label)
- end
- end
- end
- end
-
- class AbstractGemSource < Source
- def initialize
- super :RubyGems
- end
- end
-
- # GemGeneratorSource hits the mines to quarry for generators. The latest versions
- # of gems named *_generator are selected.
- class GemGeneratorSource < AbstractGemSource
- # Yield latest versions of generator gems.
- def each
- dependency = Gem::Dependency.new(/_generator$/, Gem::Requirement.default)
- Gem::cache.search(dependency).inject({}) { |latest, gem|
- hem = latest[gem.name]
- latest[gem.name] = gem if hem.nil? or gem.version > hem.version
- latest
- }.values.each { |gem|
- yield Spec.new(gem.name.sub(/_generator$/, ''), gem.full_gem_path, label)
- }
- end
- end
-
- # GemPathSource looks for generators within any RubyGem's /rails_generators/<generator_name>_generator.rb file.
- class GemPathSource < AbstractGemSource
- # Yield each generator within rails_generator subdirectories.
- def each
- generator_full_paths.each do |generator|
- yield Spec.new(File.basename(generator).sub(/_generator.rb$/, ''), File.dirname(generator), label)
- end
- end
-
- private
- def generator_full_paths
- @generator_full_paths ||=
- Gem::cache.inject({}) do |latest, name_gem|
- name, gem = name_gem
- hem = latest[gem.name]
- latest[gem.name] = gem if hem.nil? or gem.version > hem.version
- latest
- end.values.inject([]) do |mem, gem|
- Dir[gem.full_gem_path + '/{rails_,}generators/**/*_generator.rb'].each do |generator|
- mem << generator
- end
- mem
- end
- end
- end
-
- end
-end