From 0efedf2a30a12cdaa261556e3684c630690afe0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 30 Aug 2009 17:58:20 +0200 Subject: Ensure scaffold works properly even if plural name is given. [#3062] --- railties/lib/generators/base.rb | 52 ++++++++++++++- .../generators/erb/scaffold/scaffold_generator.rb | 3 +- railties/lib/generators/named_base.rb | 62 ------------------ .../rails/resource/resource_generator.rb | 16 ++--- .../rails/scaffold/scaffold_generator.rb | 3 +- .../scaffold_controller_generator.rb | 5 +- railties/lib/generators/resource_helpers.rb | 74 ++++++++++++++++++++++ .../test_unit/scaffold/scaffold_generator.rb | 3 +- 8 files changed, 137 insertions(+), 81 deletions(-) create mode 100644 railties/lib/generators/resource_helpers.rb diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb index cbe9c0a49d..c5d769b6ed 100644 --- a/railties/lib/generators/base.rb +++ b/railties/lib/generators/base.rb @@ -9,6 +9,8 @@ module Rails include Thor::Actions include Rails::Generators::Actions + add_runtime_options! + # Automatically sets the source root based on the class name. # def self.source_root @@ -45,8 +47,10 @@ module Rails # # ==== Examples # - # class ControllerGenerator < Rails::Generators::Base - # hook_for :test_framework, :aliases => "-t" + # module Rails::Generators + # class ControllerGenerator < Base + # hook_for :test_framework, :aliases => "-t" + # end # end # # The example above will create a test framework option and will invoke @@ -64,7 +68,49 @@ module Rails # 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: + # ==== Options + # + # This lookup can be customized with two options: :base and :as. The first + # is the root module value and in the example above defaults to "rails". + # The later defaults to the generator name, without the "Generator" ending. + # + # Let's suppose you are creating a generator that needs to invoke the + # controller generator from test unit. Your first attempt is: + # + # class AwesomeGenerator < Rails::Generators::Base + # hook_for :test_framework + # end + # + # The lookup in this case for test_unit as input is: + # + # "test_unit:generators:awesome", "test_unit" + # + # Which is not the desired the lookup. You can change it by providing the + # :as option: + # + # class AwesomeGenerator < Rails::Generators::Base + # hook_for :test_framework, :as => :controller + # end + # + # And now it will lookup at: + # + # "test_unit:generators:awesome", "test_unit" + # + # Similarly, if you want it to also lookup in the rails namespace, you just + # need to provide the :base value: + # + # class AwesomeGenerator < Rails::Generators::Base + # hook_for :test_framework, :base => :rails, :as => :controller + # end + # + # And the lookup is exactly the same as previously: + # + # "rails:generators:test_unit", "test_unit:generators:controller", "test_unit" + # + # ==== Switches + # + # All hooks come with switches for user interface. If the user don't want + # to use any test framework, he can do: # # ruby script/generate controller Account --skip-test-framework # diff --git a/railties/lib/generators/erb/scaffold/scaffold_generator.rb b/railties/lib/generators/erb/scaffold/scaffold_generator.rb index f146a1b1da..d51dc7d725 100644 --- a/railties/lib/generators/erb/scaffold/scaffold_generator.rb +++ b/railties/lib/generators/erb/scaffold/scaffold_generator.rb @@ -1,9 +1,10 @@ require 'generators/erb' +require 'generators/resource_helpers' module Erb module Generators class ScaffoldGenerator < Base - include Rails::Generators::ScaffoldBase + include Rails::Generators::ResourceHelpers argument :attributes, :type => :array, :default => [], :banner => "field:type field:type" diff --git a/railties/lib/generators/named_base.rb b/railties/lib/generators/named_base.rb index cd7aa61b50..b6ac05f482 100644 --- a/railties/lib/generators/named_base.rb +++ b/railties/lib/generators/named_base.rb @@ -97,67 +97,5 @@ module Rails end end end - - # Deal with controller names on scaffold. Also provide helpers to deal with - # ActionORM. - # - module ScaffoldBase - def self.included(base) #:nodoc: - base.send :attr_reader, :controller_name, :controller_class_name, :controller_file_name, - :controller_class_path, :controller_file_path - end - - # Set controller variables on initialization. - # - def initialize(*args) #:nodoc: - super - @controller_name = name.pluralize - - base_name, @controller_class_path, @controller_file_path, class_nesting, class_nesting_depth = extract_modules(@controller_name) - class_name_without_nesting, @controller_file_name, controller_plural_name = inflect_names(base_name) - - @controller_class_name = if class_nesting.empty? - class_name_without_nesting - else - "#{class_nesting}::#{class_name_without_nesting}" - end - end - - protected - - # Loads the ORM::Generators::ActiveModel class. This class is responsable - # to tell scaffold entities how to generate an specific method for the - # ORM. Check Rails::Generators::ActiveModel for more information. - # - def orm_class - @orm_class ||= begin - # Raise an error if the class_option :orm was not defined. - unless self.class.class_options[:orm] - raise "You need to have :orm as class option to invoke orm_class and orm_instance" - end - - action_orm = "#{options[:orm].to_s.classify}::Generators::ActiveModel" - - # If the orm was not loaded, try to load it at "generators/orm", - # for example "generators/active_record" or "generators/sequel". - begin - klass = action_orm.constantize - rescue NameError - require "generators/#{options[:orm]}" - end - - # Try once again after loading the file with success. - klass ||= action_orm.constantize - rescue Exception => e - raise Error, "Could not load #{action_orm}, skipping controller. Error: #{e.message}." - end - end - - # Initialize ORM::Generators::ActiveModel to access instance methods. - # - def orm_instance(name=file_name) - @orm_instance ||= @orm_class.new(name) - end - end end end diff --git a/railties/lib/generators/rails/resource/resource_generator.rb b/railties/lib/generators/rails/resource/resource_generator.rb index 70babc0550..9abb8bbeaf 100644 --- a/railties/lib/generators/rails/resource/resource_generator.rb +++ b/railties/lib/generators/rails/resource/resource_generator.rb @@ -1,25 +1,19 @@ require 'generators/rails/model/model_generator' +require 'generators/resource_helpers' module Rails module Generators class ResourceGenerator < ModelGenerator #metagenerator + include ResourceHelpers + hook_for :resource_controller, :required => true do |base, controller| - base.invoke controller, [ base.name.pluralize, base.options[:actions] ] + base.invoke controller, [ base.controller_name, base.options[:actions] ] end class_option :actions, :type => :array, :banner => "ACTION ACTION", :default => [], :desc => "Actions for the resource controller" - class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller" - class_option :force_plural, :type => :boolean, :desc => "Forces the use of a plural ModelName" - - def initialize(*args) - super - if name == name.pluralize && !options[:force_plural] - say "Plural version of the model detected, using singularized version. Override with --force-plural." - name.replace name.singularize - end - end + class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller" def add_resource_route route "map.resource#{:s unless options[:singleton]} :#{pluralize?(file_name)}" diff --git a/railties/lib/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/generators/rails/scaffold/scaffold_generator.rb index af44c8ba65..fdea5bf52b 100644 --- a/railties/lib/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/generators/rails/scaffold/scaffold_generator.rb @@ -3,7 +3,8 @@ require 'generators/rails/resource/resource_generator' module Rails module Generators class ScaffoldGenerator < ResourceGenerator #metagenerator - remove_hook_for :actions, :resource_controller + remove_hook_for :resource_controller + remove_class_option :actions hook_for :scaffold_controller, :required => true hook_for :stylesheets diff --git a/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb index 972be5a33b..228cdecb14 100644 --- a/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -1,8 +1,9 @@ +require 'generators/resource_helpers' + module Rails module Generators class ScaffoldControllerGenerator < NamedBase - # Add controller methods and ActionORM settings. - include ScaffoldBase + include ResourceHelpers check_class_collision :suffix => "Controller" diff --git a/railties/lib/generators/resource_helpers.rb b/railties/lib/generators/resource_helpers.rb new file mode 100644 index 0000000000..ba1444652d --- /dev/null +++ b/railties/lib/generators/resource_helpers.rb @@ -0,0 +1,74 @@ +module Rails + module Generators + # Deal with controller names on scaffold and add some helpers to deal with + # ActiveModel. + # + module ResourceHelpers + def self.included(base) #:nodoc: + base.send :attr_reader, :controller_name, :controller_class_name, :controller_file_name, + :controller_class_path, :controller_file_path + + base.send :class_option, :force_plural, :type => :boolean, :desc => "Forces the use of a plural ModelName" + end + + # Set controller variables on initialization. + # + def initialize(*args) #:nodoc: + super + + if name == name.pluralize && !options[:force_plural] + say "Plural version of the model detected, using singularized version. Override with --force-plural." + name.replace name.singularize + assign_names!(self.name) + end + + @controller_name = name.pluralize + + base_name, @controller_class_path, @controller_file_path, class_nesting, class_nesting_depth = extract_modules(@controller_name) + class_name_without_nesting, @controller_file_name, controller_plural_name = inflect_names(base_name) + + @controller_class_name = if class_nesting.empty? + class_name_without_nesting + else + "#{class_nesting}::#{class_name_without_nesting}" + end + end + + protected + + # Loads the ORM::Generators::ActiveModel class. This class is responsable + # to tell scaffold entities how to generate an specific method for the + # ORM. Check Rails::Generators::ActiveModel for more information. + # + def orm_class + @orm_class ||= begin + # Raise an error if the class_option :orm was not defined. + unless self.class.class_options[:orm] + raise "You need to have :orm as class option to invoke orm_class and orm_instance" + end + + active_model = "#{options[:orm].to_s.classify}::Generators::ActiveModel" + + # If the orm was not loaded, try to load it at "generators/orm", + # for example "generators/active_record" or "generators/sequel". + begin + klass = active_model.constantize + rescue NameError + require "generators/#{options[:orm]}" + end + + # Try once again after loading the file with success. + klass ||= active_model.constantize + rescue Exception => e + raise Error, "Could not load #{active_model}, skipping controller. Error: #{e.message}." + end + end + + # Initialize ORM::Generators::ActiveModel to access instance methods. + # + def orm_instance(name=file_name) + @orm_instance ||= @orm_class.new(name) + end + end + end +end diff --git a/railties/lib/generators/test_unit/scaffold/scaffold_generator.rb b/railties/lib/generators/test_unit/scaffold/scaffold_generator.rb index 78fcea1e9c..a8f9c8bd79 100644 --- a/railties/lib/generators/test_unit/scaffold/scaffold_generator.rb +++ b/railties/lib/generators/test_unit/scaffold/scaffold_generator.rb @@ -1,9 +1,10 @@ require 'generators/test_unit' +require 'generators/resource_helpers' module TestUnit module Generators class ScaffoldGenerator < Base - include Rails::Generators::ScaffoldBase + include Rails::Generators::ResourceHelpers class_option :singleton, :type => :boolean, :desc => "Supply to create a singleton controller" check_class_collision :suffix => "ControllerTest" -- cgit v1.2.3