From 6774e12afa0f29442aa612ddf6e51d5a1b7a4356 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Wed, 6 Oct 2010 11:07:09 +0200 Subject: Clean up the builder abstraction in AppGenerator. This commit may be reverted once documentation and a proper way to handle actions are added. --- .../rails/generators/rails/app/app_generator.rb | 247 +++++---------------- railties/test/generators/app_generator_test.rb | 68 +----- 2 files changed, 55 insertions(+), 260 deletions(-) (limited to 'railties') diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 2715483914..be09698787 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -6,152 +6,12 @@ require 'open-uri' require 'uri' module Rails - module ActionMethods - attr_reader :options - - def initialize(generator) - @generator = generator - @options = generator.options - end - - private - %w(template copy_file directory empty_directory inside - empty_directory_with_gitkeep create_file chmod shebang).each do |method| - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def #{method}(*args, &block) - @generator.send(:#{method}, *args, &block) - end - RUBY - end - - # TODO: Remove once this is fully in place - def method_missing(meth, *args, &block) - STDERR.puts "Calling #{meth} with #{args.inspect} with #{block}" - @generator.send(meth, *args, &block) - end - end - - class AppBuilder - def rakefile - template "Rakefile" - end - - def readme - copy_file "README" - end - - def gemfile - template "Gemfile" - end - - def configru - template "config.ru" - end - - def gitignore - copy_file "gitignore", ".gitignore" - end - - def app - directory 'app' - end - - def config - empty_directory "config" - - inside "config" do - template "routes.rb" - template "application.rb" - template "environment.rb" - - directory "environments" - directory "initializers" - directory "locales" - end - end - - def database_yml - template "config/databases/#{@options[:database]}.yml", "config/database.yml" - end - - def db - directory "db" - end - - def doc - directory "doc" - end - - def lib - empty_directory "lib" - empty_directory_with_gitkeep "lib/tasks" - end - - def log - empty_directory "log" - - inside "log" do - %w( server production development test ).each do |file| - create_file "#{file}.log" - chmod "#{file}.log", 0666, :verbose => false - end - end - end - - def public_directory - directory "public", "public", :recursive => false - end - - def images - directory "public/images" - end - - def stylesheets - empty_directory_with_gitkeep "public/stylesheets" - end - - def javascripts - unless options[:skip_prototype] - directory "public/javascripts" - else - empty_directory_with_gitkeep "public/javascripts" - create_file "public/javascripts/application.js" - end - end - - def script - directory "script" do |content| - "#{shebang}\n" + content - end - chmod "script", 0755, :verbose => false - end - - def test - directory "test" - end - - def tmp - empty_directory "tmp" - - inside "tmp" do - %w(sessions sockets cache pids).each do |dir| - empty_directory(dir) - end - end - end - - def vendor_plugins - empty_directory_with_gitkeep "vendor/plugins" - end - end - module Generators # We need to store the RAILS_DEV_PATH in a constant, otherwise the path # can change in Ruby 1.8.7 when we FileUtils.cd. RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__)) - RESERVED_NAMES = %w[application destroy benchmarker profiler - plugin runner test] + RESERVED_NAMES = %w(application destroy benchmarker profiler plugin runner test) class AppGenerator < Base DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) @@ -164,9 +24,6 @@ module Rails class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" - class_option :builder, :type => :string, :aliases => "-b", - :desc => "Path to an application builder (can be a filesystem path or URL)" - class_option :template, :type => :string, :aliases => "-m", :desc => "Path to an application template (can be a filesystem path or URL)" @@ -200,7 +57,6 @@ module Rails def initialize(*args) raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank? - @original_wd = Dir.pwd super @@ -220,19 +76,29 @@ module Rails end def create_root_files - build(:readme) - build(:rakefile) - build(:configru) - build(:gitignore) unless options[:skip_git] - build(:gemfile) unless options[:skip_gemfile] + copy_file "README" + template "Rakefile" + template "config.ru" + copy_file "gitignore", ".gitignore" unless options[:skip_git] + template "Gemfile" unless options[:skip_gemfile] end def create_app_files - build(:app) + directory 'app' end def create_config_files - build(:config) + empty_directory "config" + + inside "config" do + template "routes.rb" + template "application.rb" + template "environment.rb" + + directory "environments" + directory "initializers" + directory "locales" + end end def create_boot_file @@ -241,59 +107,77 @@ module Rails def create_active_record_files return if options[:skip_active_record] - build(:database_yml) + template "config/databases/#{@options[:database]}.yml", "config/database.yml" end def create_db_files - build(:db) + directory "db" end def create_doc_files - build(:doc) + directory "doc" end def create_lib_files - build(:lib) + empty_directory "lib" + empty_directory_with_gitkeep "lib/tasks" end def create_log_files - build(:log) + empty_directory "log" + + inside "log" do + %w( server production development test ).each do |file| + create_file "#{file}.log" + chmod "#{file}.log", 0666, :verbose => false + end + end end def create_public_files - build(:public_directory) + directory "public", "public", :recursive => false end def create_public_image_files - build(:images) + directory "public/images" end def create_public_stylesheets_files - build(:stylesheets) + empty_directory_with_gitkeep "public/stylesheets" end - def create_prototype_files - build(:javascripts) + def create_public_javascripts_files + unless options[:skip_prototype] + directory "public/javascripts" + else + empty_directory_with_gitkeep "public/javascripts" + create_file "public/javascripts/application.js" + end end def create_script_files - build(:script) + directory "script" do |content| + "#{shebang}\n" + content + end + chmod "script", 0755, :verbose => false end def create_test_files - build(:test) unless options[:skip_test_unit] + directory "test" unless options[:skip_test_unit] end def create_tmp_files - build(:tmp) - end + empty_directory "tmp" - def create_vendor_files - build(:vendor_plugins) + inside "tmp" do + %w(sessions sockets cache pids).each do |dir| + empty_directory(dir) + end + end end - def finish_template - build(:leftovers) + def create_vendor_files + empty_directory_with_gitkeep "vendor/plugins" end def apply_rails_template @@ -313,29 +197,6 @@ module Rails "rails new #{self.arguments.map(&:usage).join(' ')} [options]" end - def builder - @builder ||= begin - if path = options[:builder] - if URI(path).is_a?(URI::HTTP) - contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read } - else - contents = open(File.expand_path(path, @original_wd)) {|io| io.read } - end - - prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1) - instance_eval(&prok) - end - - builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder - builder_class.send(:include, ActionMethods) - builder_class.new(self) - end - end - - def build(meth, *args) - builder.send(meth, *args) if builder.respond_to?(meth) - end - def set_default_accessors! self.rails_template = case options[:template] when /^http:\/\// diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 3653b067c8..3bd8770710 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -261,70 +261,4 @@ protected silence(:stdout){ generator.send(*args, &block) } end -end - -class CustomAppGeneratorTest < Rails::Generators::TestCase - include GeneratorsTestHelper - tests Rails::Generators::AppGenerator - - arguments [destination_root] - - def setup - Rails.application = TestApp::Application - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - end - - def teardown - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - Object.class_eval { remove_const :AppBuilder if const_defined?(:AppBuilder) } - Rails.application = TestApp::Application.instance - end - - def test_builder_option_with_empty_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/empty_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_no_file path } - end - - def test_builder_option_with_simple_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_relative_path - here = File.expand_path(File.dirname(__FILE__)) - FileUtils.cd(here) - run_generator([destination_root, "-b", "../fixtures/lib/simple_builder.rb"]) - (DEFAULT_APP_FILES - ['config.ru']).each{ |path| assert_no_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_tweak_app_builder - FileUtils.cd(Rails.root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/tweak_builder.rb"]) - DEFAULT_APP_FILES.each{ |path| assert_file path } - assert_file "config.ru", %[run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] }] - end - - def test_builder_option_with_http - path = "http://gist.github.com/103208.txt" - template = "class AppBuilder; end" - template.instance_eval "def read; self; end" # Make the string respond to read - - generator([destination_root], :builder => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - capture(:stdout) { generator.invoke_all } - - DEFAULT_APP_FILES.each{ |path| assert_no_file path } - end - -protected - - def action(*args, &block) - silence(:stdout){ generator.send(*args, &block) } - end -end +end \ No newline at end of file -- cgit v1.2.3