diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb index e5e2c03b48..5fa6c72f43 100644 --- a/railties/lib/generators/base.rb +++ b/railties/lib/generators/base.rb @@ -3,15 +3,17 @@ require 'generators/actions' module Rails module Generators DEFAULTS = { - :orm => 'active_record', + :fixture => true, :helper => true, + :orm => 'active_record', :test_framework => 'test_unit', :template_engine => 'erb' } ALIASES = { + :fixture_replacement => '-r', + :helper => '-l', :orm => '-o', - :helper => '-v', :test_framework => '-t', :template_engine => '-e' } @@ -70,11 +72,13 @@ module Rails # # ruby script/generate controller Account --test-framework=test_unit # - # The controller generator will then invoke "test_unit:generators:controller". - # If it can't be found it then tries to invoke only "test_unit". + # The controller generator will then try to invoke the following generators: # - # This allows any test framework to hook into Rails as long as it - # provides a "test_framework:generators:controller" generator. + # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # + # In this case, the "test_unit:generators:controller" is available and is + # invoked. This allows any test framework to hook into Rails as long as it + # provides any of the hooks above. # # Finally, if the user don't want to use any test framework, he can do: # @@ -84,12 +88,35 @@ module Rails # # ruby script/generate controller Account --no-test-framework # + # ==== Another example + # + # Another example of invoke_for hooks is fixture replacement tools. + # Consider this TestUnit model generator: + # + # class ModelGenerator < TestUnit::Generators::Base + # invoke_for :fixture_replacement, :aliases => "-r" + # end + # + # When invoked as: + # + # ruby script/generate test_unit:model Account -r fixjour + # + # It will lookup for any of these generators: + # + # "test_unit:generators:fixjour", "fixjour:generators:model", "fixjour" + # + # Fixjour can choose any of these hooks to implement. For example, if + # Fixjour has different output for rspec and test_unit, it will likely + # implement the first hook. However if the output is the same for both, + # it will implement the second or the third depending on the number of + # generators it has. + # def self.invoke_for(*names) default_options = names.extract_options! names.each do |name| options = default_options.dup - options[:desc] ||= "#{name.to_s.humanize} to be used" + options[:desc] ||= "#{name.to_s.humanize} to be invoked" options[:banner] ||= "NAME" options[:aliases] ||= ALIASES[name] @@ -100,13 +127,12 @@ module Rails return unless options[#{name.inspect}] klass = Rails::Generators.find_by_namespace(options[#{name.inspect}], - nil, self.class.generator_name) + self.class.base_name, self.class.generator_name) if klass invoke klass else - task = "\#{options[#{name.inspect}]}:generators:\#{self.class.generator_name}" - say "Could not find and invoke '\#{task}'." + say "Could not find and invoke '\#{options[#{name.inspect}]}'." end end METHOD @@ -140,11 +166,7 @@ module Rails default_options = names.extract_options! names.each do |name| - options = default_options.dup - options[:desc] ||= "Indicates when to use #{name.to_s.humanize}" - - # TODO Reverse --name to --skip-name if default is given. - class_option name, options.merge!(:type => :boolean, :default => DEFAULTS[name] || false) + conditional_class_option name, default_options.dup class_eval <<-METHOD, __FILE__, __LINE__ def invoke_if_#{name} @@ -156,7 +178,7 @@ module Rails if klass invoke klass else - say "Could not find and invoke '#{name.inspect}'." + say "Could not find and invoke '#{name}'." end end METHOD @@ -220,6 +242,14 @@ module Rails end end + # Creates a conditional class option with type boolean, default value + # lookup and default description. + # + def self.conditional_class_option(name, options={}) + options[:desc] ||= "Indicates when to generate #{name.to_s.humanize.downcase}" + class_option name, options.merge!(:type => :boolean, :default => DEFAULTS[name] || false) + end + # Small macro to add ruby as an option to the generator with proper # default value plus an instance helper method called shebang. # diff --git a/railties/lib/generators/test_unit/model/model_generator.rb b/railties/lib/generators/test_unit/model/model_generator.rb index 901ed70468..6aff027107 100644 --- a/railties/lib/generators/test_unit/model/model_generator.rb +++ b/railties/lib/generators/test_unit/model/model_generator.rb @@ -4,18 +4,16 @@ module TestUnit argument :attributes, :type => :hash, :default => {}, :banner => "field:type, field:type" check_class_collision :suffix => "Test" - - # TODO Add DEFAULTS support - class_option :skip_fixture, :type => :boolean, :default => false, - :desc => "Don't generate a fixture file" + conditional_class_option :fixture def create_test_file template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb") end - # TODO Add fixture replacement support + invoke_for :fixture_replacement + def create_fixture_file - unless options[:skip_fixture] + if options[:fixture] && options[:fixture_replacement].nil? template 'fixtures.yml', File.join('test/fixtures', "#{table_name}.yml") end end diff --git a/railties/test/generators/helper_generator_test.rb b/railties/test/generators/helper_generator_test.rb index b2533e5315..41e1e1dce2 100644 --- a/railties/test/generators/helper_generator_test.rb +++ b/railties/test/generators/helper_generator_test.rb @@ -20,7 +20,7 @@ class HelperGeneratorTest < GeneratorsTestCase def test_logs_if_the_test_framework_cannot_be_found content = run_generator ["admin", "--test-framework=unknown"] - assert_match /Could not find and invoke 'unknown:generators:helper'/, content + assert_match /Could not find and invoke 'unknown'/, content end def test_check_class_collision diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index 3e5dc60361..5d21da3dd1 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -36,7 +36,7 @@ class MailerGeneratorTest < GeneratorsTestCase def test_logs_if_the_template_engine_cannot_be_found content = run_generator ["notifier", "foo", "bar", "--template-engine=unknown"] - assert_match /Could not find and invoke 'unknown:generators:mailer'/, content + assert_match /Could not find and invoke 'unknown'/, content end def test_actions_are_turned_into_methods diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb index 425c4f581a..904f77242d 100644 --- a/railties/test/generators/model_generator_test.rb +++ b/railties/test/generators/model_generator_test.rb @@ -22,6 +22,12 @@ class ModelGeneratorTest < GeneratorsTestCase assert_no_file "test/fixtures/accounts.yml" end + def test_fixtures_are_skipped_if_fixture_replacement_is_given + content = run_generator ["account", "-r", "fixjour"] + assert_match /Could not find and invoke 'fixjour'/, content + assert_no_file "test/fixtures/accounts.yml" + end + def test_check_class_collision content = capture(:stderr){ run_generator ["object"] } assert_match /The name 'Object' is either already used in your application or reserved/, content diff --git a/railties/test/generators/observer_generator_test.rb b/railties/test/generators/observer_generator_test.rb index e2b027028a..3707b70c7e 100644 --- a/railties/test/generators/observer_generator_test.rb +++ b/railties/test/generators/observer_generator_test.rb @@ -23,7 +23,7 @@ class ObserverGeneratorTest < GeneratorsTestCase def test_logs_if_the_test_framework_cannot_be_found content = run_generator ["account", "--test-framework=unknown"] - assert_match /Could not find and invoke 'unknown:generators:observer'/, content + assert_match /Could not find and invoke 'unknown'/, content end protected diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 3f2b27c518..9e7b597739 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -27,7 +27,7 @@ class PluginGeneratorTest < GeneratorsTestCase def test_logs_if_the_test_framework_cannot_be_found content = run_generator ["plugin_fu", "--test-framework=unknown"] - assert_match /Could not find and invoke 'unknown:generators:plugin'/, content + assert_match /Could not find and invoke 'unknown'/, content end def test_creates_tasks_if_required