diff options
Diffstat (limited to 'railties/lib/rails_generator/lookup.rb')
-rw-r--r-- | railties/lib/rails_generator/lookup.rb | 249 |
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 |