diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb index d1543e8d9420e172816ab82d17ee8c9fbbf1c578..c1a384647caa10fc975dec8e9437bb04fac27537 100644 --- a/railties/lib/generators/base.rb +++ b/railties/lib/generators/base.rb @@ -91,13 +91,29 @@ def self.namespace(name=nil) # # ruby script/generate controller Account --no-test-framework # - def self.hook_for(*names) + # ==== Custom invocations + # + # You can also supply a block to hook for to customize how the hook is + # going to be invoked. The block receives two parameters, an instance + # of the current class and the klass to be invoked. + # + # For example, in the resource generator, the controller should be invoked + # with a pluralized class name. By default, it is invoked with the same + # name as the resource generator, which is singular. To change this, we + # can give a block to customize how the controller can be invoked. + # + # hook_for :resource_controller do |instance, controller| + # instance.invoke controller, [ instance.name.pluralize ] + # end + # + def self.hook_for(*names, &block) default_class_options(*names) options = names.extract_options! verbose = options.fetch(:verbose, :blue) names.each do |name| invocations << [ name, base_name, generator_name ] + invocation_blocks[name] = block if block_given? class_eval <<-METHOD, __FILE__, __LINE__ def invoke_for_#{name} @@ -108,7 +124,7 @@ def invoke_for_#{name} if klass say_status :invoke, options[#{name.inspect}], #{verbose.inspect} - invoke klass + invoke_class_with_block #{name.inspect}, klass else say "Could not find and invoke '\#{options[#{name.inspect}]}'." end @@ -140,13 +156,19 @@ def invoke_for_#{name} # # "rails:generators:webrat", "webrat:generators:controller", "webrat" # - def self.invoke_if(*names) + # ==== Custom invocations + # + # This method accepts custom invocations as in hook_for. Check hook_for + # for usage and examples. + # + def self.invoke_if(*names, &block) conditional_class_options(*names) options = names.extract_options! verbose = options.fetch(:verbose, :blue) names.each do |name| invocations << [ name, base_name, generator_name ] + invocation_blocks[name] = block if block_given? class_eval <<-METHOD, __FILE__, __LINE__ def invoke_if_#{name} @@ -157,7 +179,7 @@ def invoke_if_#{name} if klass say_status :invoke, #{name.inspect}, #{verbose.inspect} - invoke klass + invoke_class_with_block #{name.inspect}, klass else say "Could not find and invoke '#{name}'." end @@ -168,6 +190,18 @@ def invoke_if_#{name} protected + # This is the common method that both hook_for and invoke_if use to + # invoke a class. It searches for a block in the invocation blocks + # in case the user wants to customize how the class is invoked. + # + def invoke_class_with_block(name, klass) #:nodoc: + if block = self.class.invocation_blocks[name] + block.call(self, klass) + else + invoke klass + end + end + # Check whether the given class names are already taken by user # application or Ruby on Rails. # @@ -229,6 +263,12 @@ def self.invocations #:nodoc: @invocations ||= from_superclass(:invocations, []) end + # Stores invocation blocks used on hook_for and invoke_if. + # + def self.invocation_blocks #:nodoc: + @invocation_blocks ||= from_superclass(:invocation_blocks, {}) + end + # Creates a conditional class option with type boolean, default value # lookup and default description. # diff --git a/railties/lib/generators/rails/resource/resource_generator.rb b/railties/lib/generators/rails/resource/resource_generator.rb index f61e55a01ed88172a445256aba585ad10de9b216..8d787aaa75affc8395be9442602fda006928840a 100644 --- a/railties/lib/generators/rails/resource/resource_generator.rb +++ b/railties/lib/generators/rails/resource/resource_generator.rb @@ -3,7 +3,9 @@ module Rails module Generators class ResourceGenerator < ModelGenerator - hook_for :resource_controller + hook_for :resource_controller do |base, controller| + base.invoke controller, [ base.name.pluralize, base.options[:actions] ] + end class_option :actions, :type => :array, :default => [], :banner => "ACTION ACTION", :desc => "Actions for the resource controller", :aliases => "-a" @@ -11,25 +13,8 @@ class ResourceGenerator < ModelGenerator class_option :singleton, :type => :boolean, :default => false, :aliases => "-i", :desc => "Supply to create a singleton controller" - def invoke_for_resource_controller - return unless options[:resource_controller] - - klass = Rails::Generators.find_by_namespace(options[:resource_controller], :rails, :controller) - - if klass - args = [] - args << pluralize?(class_name) - args << options[:actions] - - say_status :invoke, options[:resource_controller], :blue - klass.new(args, options.dup, _overrides_config).invoke(:all) - else - say "Could not find and invoke '#{options[:resource_controller]}'." - end - end - def add_resource_route - route "map.resource#{"s" unless options[:singleton]} :#{pluralize?(file_name)}" + route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" end protected diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 6f0bad06b90db9610cfbf593e07f8282d6d07a1b..98994f6ad20325f3035934ee25b66f14a88dfc63 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -111,7 +111,7 @@ def test_shebang_is_added_to_files def test_rails_is_frozen generator(:freeze => true, :database => "sqlite3").expects(:run).with("rake rails:freeze:edge", false) - silence(:stdout){ generator.invoke(:all) } + silence(:stdout){ generator.invoke } assert_file 'config/environment.rb', /# RAILS_GEM_VERSION/ end @@ -127,7 +127,7 @@ def test_template_is_executed_when_supplied template.instance_eval "def read; self; end" # Make the string respond to read generator(:template => path, :database => "sqlite3").expects(:open).with(path).returns(template) - assert_match /It works!/, silence(:stdout){ generator.invoke(:all) } + assert_match /It works!/, silence(:stdout){ generator.invoke } end def test_usage_read_from_file diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 9e7b5977395f1669d27b0191fc6c3cc665435d71..3388b2f6f5254d3907ae960238db3ad88a241553 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -22,7 +22,8 @@ def test_check_class_collision def test_invokes_default_test_framework run_generator - assert_file "vendor/plugins/plugin_fu/test/plugin_fu_test.rb" + assert_file "vendor/plugins/plugin_fu/test/plugin_fu_test.rb", /class PluginFuTest < ActiveSupport::TestCase/ + assert_file "vendor/plugins/plugin_fu/test/test_helper.rb" end def test_logs_if_the_test_framework_cannot_be_found diff --git a/railties/test/generators/resource_generator_test.rb b/railties/test/generators/resource_generator_test.rb index 3d856f519bcfa78712994b7ee573197ad5730862..456e6ff3eae7a70bf6d2ebd88de15d2356470183 100644 --- a/railties/test/generators/resource_generator_test.rb +++ b/railties/test/generators/resource_generator_test.rb @@ -81,12 +81,6 @@ def test_resource_routes_are_added def test_singleton_resource run_generator ["account", "--singleton"] - assert_file "app/controllers/account_controller.rb", /class AccountController < ApplicationController/ - assert_file "test/functional/account_controller_test.rb", /class AccountControllerTest < ActionController::TestCase/ - - assert_file "app/helpers/account_helper.rb", /module AccountHelper/ - assert_file "test/unit/helpers/account_helper_test.rb", /class AccountHelperTest < ActionView::TestCase/ - assert_file "config/routes.rb" do |route| assert_match /map\.resource :account$/, route end