diff options
12 files changed, 162 insertions, 55 deletions
diff --git a/railties/lib/generators.rb b/railties/lib/generators.rb index ee17242940..a923a33397 100644 --- a/railties/lib/generators.rb +++ b/railties/lib/generators.rb @@ -16,7 +16,6 @@ require 'generators/active_record' # We will need ActionORM from ActiveRecord, b  module Rails    module Generators -    mattr_accessor :load_path      # Generators load paths. First search on generators in the RAILS_ROOT, then      # look for them in rails generators. @@ -33,42 +32,6 @@ module Rails      end      load_path # Cache load paths -    # Receives paths in an array and tries to find generators for it in the load -    # path. -    # -    def self.lookup(attempts) -      generators_path = [] - -      # Traverse attempts into directory lookups. For example: -      # -      #   rails:generators:model -      # -      # Becomes: -      # -      #   generators/rails/model/model_generator.rb -      #   generators/rails/model_generator.rb -      #   generators/model_generator.rb -      # -      attempts.each do |attempt| -        paths = attempt.gsub(':generators:', ':').split(':') -        paths << "#{paths.last}_generator.rb" - -        until paths.empty? -          generators_path << File.join(*paths) -          paths.delete_at(-1) unless paths.delete_at(-2) -        end -      end - -      generators_path.uniq! -      generators_path.each do |generator_path| -        self.load_path.each do |path| -          Dir[File.join(path, generator_path)].each do |file| -            require file -          end -        end -      end -    end -      # Keep builtin generators in an Array[Array[group, name]].      #      def self.builtin @@ -114,11 +77,15 @@ module Rails        attempts << name.sub(':', ':generators:') if name.count(':') == 1        attempts << name -      unless klass = find_many_by_namespace(attempts) -        lookup(attempts) -        klass = find_many_by_namespace(attempts) +      unloaded = attempts - namespaces +      lookup(unloaded) + +      attempts.each do |namespace| +        klass = Thor::Util.find_by_namespace(namespace) +        return klass if klass        end -      klass + +      nil      end      # Show help message with available generators. @@ -133,8 +100,23 @@ module Rails        puts "Please select a generator."        puts "Builtin: #{rails.join(', ')}." -      # TODO Show others after lookup is implemented -      # puts "Others: #{others.join(', ')}." +      # Load paths and remove builtin +      paths, others = load_path.dup, [] +      paths.shift + +      paths.each do |path| +        tail = [ "*", "*", "*_generator.rb" ] + +        until tail.empty? +          others += Dir[File.join(path, *tail)].collect do |file| +            file.split('/')[-tail.size, 2].join(':').sub(/_generator\.rb$/, '') +          end +          tail.shift +        end +      end + +      others.sort! +      puts "Others: #{others.join(', ')}." unless others.empty?      end      # Receives a namespace, arguments and the behavior to invoke the generator. @@ -152,12 +134,45 @@ module Rails      protected -      def self.find_many_by_namespace(attempts) -        attempts.each do |namespace| -          klass = Thor::Util.find_by_namespace(namespace) -          return klass if klass +      # Return all defined namespaces. +      # +      def self.namespaces +        Thor::Base.subclasses.map(&:namespace) +      end + +      # Receives namespaces in an array and tries to find matching generators +      # in the load path. Each path is traversed into directory lookups. For +      # example: +      # +      #   rails:generators:model +      # +      # Becomes: +      # +      #   generators/rails/model/model_generator.rb +      #   generators/rails/model_generator.rb +      #   generators/model_generator.rb +      # +      def self.lookup(attempts) +        attempts.each do |attempt| +          generators_path = ['.'] + +          paths = attempt.gsub(':generators:', ':').split(':') +          name  = "#{paths.last}_generator.rb" + +          until paths.empty? +            generators_path.unshift File.join(*paths) +            paths.pop +          end + +          generators_path.uniq! +          generators_path = "{#{generators_path.join(',')}}" + +          self.load_path.each do |path| +            Dir[File.join(path, generators_path, name)].each do |file| +              require file +            end +          end          end -        nil        end    end diff --git a/railties/test/fixtures/lib/generators/active_record/fixjour/fixjour_generator.rb b/railties/test/fixtures/lib/generators/active_record/fixjour/fixjour_generator.rb new file mode 100644 index 0000000000..7a4edb8bcb --- /dev/null +++ b/railties/test/fixtures/lib/generators/active_record/fixjour/fixjour_generator.rb @@ -0,0 +1,8 @@ +require 'generators/active_record' + +module ActiveRecord +  module Generators +    class FixjourGenerator < Base +    end +  end +end diff --git a/railties/test/fixtures/lib/generators/fixjour_generator.rb b/railties/test/fixtures/lib/generators/fixjour_generator.rb new file mode 100644 index 0000000000..ef3e9edbed --- /dev/null +++ b/railties/test/fixtures/lib/generators/fixjour_generator.rb @@ -0,0 +1,2 @@ +class FixjourGenerator < Rails::Generators::NamedBase +end diff --git a/railties/test/fixtures/lib/generators/missing_class/missing_class_generator.rb b/railties/test/fixtures/lib/generators/missing_class/missing_class_generator.rb deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/lib/generators/missing_class/missing_class_generator.rb +++ /dev/null diff --git a/railties/test/fixtures/lib/generators/missing_class/templates/.gitignore b/railties/test/fixtures/lib/generators/missing_class/templates/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/lib/generators/missing_class/templates/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/lib/generators/missing_generator/templates/.gitignore b/railties/test/fixtures/lib/generators/missing_generator/templates/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/lib/generators/missing_generator/templates/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/lib/generators/missing_templates/.gitignore b/railties/test/fixtures/lib/generators/missing_templates/.gitignore deleted file mode 100644 index e69de29bb2..0000000000 --- a/railties/test/fixtures/lib/generators/missing_templates/.gitignore +++ /dev/null diff --git a/railties/test/fixtures/lib/generators/rails/javascripts_generator.rb b/railties/test/fixtures/lib/generators/rails/javascripts_generator.rb new file mode 100644 index 0000000000..cad5e96784 --- /dev/null +++ b/railties/test/fixtures/lib/generators/rails/javascripts_generator.rb @@ -0,0 +1,4 @@ +module Rails::Generators +  class JavascriptsGenerator < Rails::Generators::NamedBase +  end +end diff --git a/railties/test/fixtures/lib/generators/working/working_generator.rb b/railties/test/fixtures/lib/generators/working/working_generator.rb deleted file mode 100644 index 465b34319a..0000000000 --- a/railties/test/fixtures/lib/generators/working/working_generator.rb +++ /dev/null @@ -1,2 +0,0 @@ -class WorkingGenerator < Rails::Generator::NamedBase -end diff --git a/railties/test/generators/generators_test_helper.rb b/railties/test/generators/generators_test_helper.rb index 7f22197a54..2ccedf814d 100644 --- a/railties/test/generators/generators_test_helper.rb +++ b/railties/test/generators/generators_test_helper.rb @@ -1,9 +1,6 @@  require 'test/unit'  require 'fileutils' -$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" -require 'generators' -  fixtures = File.expand_path(File.join(File.dirname(__FILE__), '..', 'fixtures'))  if defined?(RAILS_ROOT)    RAILS_ROOT.replace fixtures @@ -11,6 +8,9 @@ else    RAILS_ROOT = fixtures  end +$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib" +require 'generators' +  class GeneratorsTestCase < Test::Unit::TestCase    include FileUtils diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index d076244abd..30fc837834 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -107,8 +107,8 @@ class ModelGeneratorTest < GeneratorsTestCase    end    def test_fixture_is_skipped_if_fixture_replacement_is_given -    content = run_generator ["account", "-r", "fixjour"] -    assert_match /Could not find and invoke 'fixjour'/, content +    content = run_generator ["account", "-r", "factory_girl"] +    assert_match /Could not find and invoke 'factory_girl'/, content      assert_no_file "test/fixtures/accounts.yml"    end diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb new file mode 100644 index 0000000000..ac290b10bb --- /dev/null +++ b/railties/test/generators_test.rb @@ -0,0 +1,80 @@ +require File.join(File.dirname(__FILE__), 'generators', 'generators_test_helper') +require 'generators/rails/model/model_generator' +require 'mocha' + +class GeneratorsTest < GeneratorsTestCase +  def test_invoke_when_generator_is_not_found +    output = capture(:stdout){ Rails::Generators.invoke :unknown } +    assert_equal "Could not find generator unknown.\n", output +  end + +  def test_help_when_a_generator_with_required_arguments_is_invoked_without_arguments +    output = capture(:stdout){ Rails::Generators.invoke :model, [] } +    assert_match /Description:/, output +  end + +  def test_invoke_with_default_behavior +    Rails::Generators::ModelGenerator.expects(:start).with(["Account"], :behavior => :invoke) +    Rails::Generators.invoke :model, ["Account"] +  end + +  def test_invoke_with_given_behavior +    Rails::Generators::ModelGenerator.expects(:start).with(["Account"], :behavior => :skip) +    Rails::Generators.invoke :model, ["Account"], :skip +  end + +  def test_find_by_namespace_without_base_or_context +    assert_nil Rails::Generators.find_by_namespace(:model) +  end + +  def test_find_by_namespace_with_base +    klass = Rails::Generators.find_by_namespace(:model, :rails) +    assert klass +    assert_equal "rails:generators:model", klass.namespace +  end + +  def test_find_by_namespace_with_context +    klass = Rails::Generators.find_by_namespace(:test_unit, nil, :model) +    assert klass +    assert_equal "test_unit:generators:model", klass.namespace +  end + +  def test_find_by_namespace_add_generators_to_raw_lookups +    klass = Rails::Generators.find_by_namespace("test_unit:model") +    assert klass +    assert_equal "test_unit:generators:model", klass.namespace +  end + +  def test_find_by_namespace_lookup_to_the_rails_root_folder +    klass = Rails::Generators.find_by_namespace(:fixjour) +    assert klass +    assert_equal "fixjour", klass.namespace +  end + +  def test_find_by_namespace_lookup_to_deep_rails_root_folders +    klass = Rails::Generators.find_by_namespace(:fixjour, :active_record) +    assert klass +    assert_equal "active_record:generators:fixjour", klass.namespace +  end + +  def test_find_by_namespace_lookup_traverse_folders +    klass = Rails::Generators.find_by_namespace(:javascripts, :rails) +    assert klass +    assert_equal "rails:generators:javascripts", klass.namespace +  end + +  def test_builtin_generators +    assert Rails::Generators.builtin.include? %w(rails model) +  end + +  def test_rails_generators_help_with_builtin_information +    output = capture(:stdout){ Rails::Generators.help } +    assert_match /model/, output +    assert_match /scaffold_controller/, output +  end + +  def test_rails_generators_with_others_information +    output = capture(:stdout){ Rails::Generators.help }.split("\n").last +    assert_equal "Others: active_record:fixjour, fixjour, rails:javascripts.", output +  end +end  | 
