From 8d47078a492de9e3fca61ec6894e975d570ef449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 15 Jul 2009 22:37:22 +0200 Subject: Added source_paths to rails generators. If a template is added to RAILS_ROOT/lib/templates/base/generator it will be used. For example, to customize edit.html.erb template on scaffold, just add a customized copy at RAILS_ROOT/lib/templates/erb/scaffold. --- railties/lib/generators/base.rb | 22 +++++++-- .../lib/vendor/thor-0.11.1/lib/thor/actions.rb | 54 ++++++++-------------- railties/test/generators_test.rb | 20 +++++++- 3 files changed, 55 insertions(+), 41 deletions(-) (limited to 'railties') diff --git a/railties/lib/generators/base.rb b/railties/lib/generators/base.rb index 0ef6d061ff..4c38e0f5be 100644 --- a/railties/lib/generators/base.rb +++ b/railties/lib/generators/base.rb @@ -6,15 +6,16 @@ module Rails end class Base < Thor::Group + include Thor::Actions + include Rails::Generators::Actions + # Automatically sets the source root based on the class name. # def self.source_root - File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates')) + @_rails_source_root ||= File.expand_path(File.join(File.dirname(__FILE__), + base_name, generator_name, 'templates')) end - include Thor::Actions - include Rails::Generators::Actions - # Tries to get the description from a USAGE file one folder above the source # root otherwise uses a default description. # @@ -148,6 +149,19 @@ module Rails super(name, options) end + # Cache source root and add lib/generators/base/generator/templates to + # source paths. + # + def self.inherited(base) #:nodoc: + super + base.source_root # Cache source root + + if defined?(RAILS_ROOT) && base.name !~ /Base$/ + path = File.expand_path(File.join(RAILS_ROOT, 'lib', 'templates')) + base.source_paths << File.join(path, base.base_name, base.generator_name) + end + end + protected # Check whether the given class names are already taken by user diff --git a/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb b/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb index 939339088a..44dfa1b14c 100644 --- a/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb +++ b/railties/lib/vendor/thor-0.11.1/lib/thor/actions.rb @@ -28,45 +28,27 @@ class Thor end module ClassMethods - # Hold source paths used by Thor::Actions. + # Hold source paths for one Thor instance. source_paths_for_search is the + # method responsible to gather source_paths from this current class, + # inherited paths and the source root. # def source_paths - @source_paths ||= from_superclass(:source_paths, []) + @source_paths ||= [] end - # On inheritance, add source root to source paths so dynamic source_root - # (that depends on the class name, for example) are cached properly. + # Returns the source paths in the following order: # - def inherited(base) #:nodoc: - super - base.source_paths - if base.respond_to?(:source_root) && !base.source_paths.include?(base.source_root) - base.source_paths.unshift(base.source_root) - end - end - - # Deal with source root cache in source_paths. source_paths in the - # inheritance chain are tricky to implement because: - # - # 1) We have to ensure that paths from the parent class appears later in - # the source paths array. + # 1) This class source paths + # 2) Source root + # 3) Parents source paths # - # 2) Whenever source_root is added, it has to be cached because __FILE__ - # in ruby returns relative locations. - # - # 3) If someone wants to add source paths dinamically, added paths have - # to come before the source root. - # - # This method basically check if source root was added and put it between - # the inherited paths and the user added paths. - # - def singleton_method_added(method) #:nodoc: - if method == :source_root - inherited_paths = from_superclass(:source_paths, []) - - self.source_paths.reject!{ |path| inherited_paths.include?(path) } - self.source_paths.push(*self.source_root) - self.source_paths.concat(inherited_paths) + def source_paths_for_search + @source_paths_for_search ||= begin + paths = [] + paths += self.source_paths + paths << self.source_root if self.respond_to?(:source_root) + paths += from_superclass(:source_paths, []) + paths end end end @@ -132,14 +114,14 @@ class Thor # def find_in_source_paths(file) relative_root = relative_to_original_destination_root(destination_root, false) - source_file = nil + paths = self.class.source_paths_for_search - self.class.source_paths.each do |source| + paths.each do |source| source_file = File.expand_path(file, File.join(source, relative_root)) return source_file if File.exists?(source_file) end - if self.class.source_paths.empty? + if paths.empty? raise Error, "You don't have any source path defined for class #{self.class.name}. To fix this, " << "you can define a source_root in your class." else diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb index 964def4158..78c05f2eb8 100644 --- a/railties/test/generators_test.rb +++ b/railties/test/generators_test.rb @@ -84,7 +84,7 @@ class GeneratorsTest < GeneratorsTestCase assert_equal "Others: active_record:fixjour, fixjour, mspec, rails:javascripts, wrong.", output end - def test_warning_is_raised_if_generator_cant_be_loaded + def test_warning_is_shown_if_generator_cant_be_loaded output = capture(:stderr){ Rails::Generators.find_by_namespace(:wrong) } assert_match /\[WARNING\] Could not load generator at/, output assert_match /Error: uninitialized constant Rails::Generator/, output @@ -96,4 +96,22 @@ class GeneratorsTest < GeneratorsTestCase ensure Thor::Base.shell = Thor::Shell::Color end + + def test_rails_root_templates + template = File.join(RAILS_ROOT, "lib", "templates", "active_record", "model", "model.rb") + + # Create template + mkdir_p(File.dirname(template)) + File.open(template, 'w'){ |f| f.write "empty" } + + output = capture(:stdout) do + Rails::Generators.invoke :model, ["user"], :destination_root => destination_root + end + + assert_file "app/models/user.rb" do |content| + assert_equal "empty", content + end + ensure + rm_rf File.dirname(template) + end end -- cgit v1.2.3