From cfcea1d53ae5ce38a7cbeb41e05958dc009988b0 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 15 Oct 2010 17:46:31 +0300 Subject: [PATCH 01/36] Added 'rails plugin new' generator which generates gem plugin skeleton. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This command is based on enginex gem by José Valim. It generates gem structure and ads dummy application into test/dummy. This can be used to start developing any kind of extension for rails 3. --- railties/lib/rails/cli.rb | 7 +- railties/lib/rails/commands/plugin_new.rb | 16 ++ .../rails/plugin_new/plugin_new_generator.rb | 225 ++++++++++++++++++ .../rails/plugin_new/templates/%name%.gemspec | 9 + .../rails/plugin_new/templates/Gemfile | 11 + .../rails/plugin_new/templates/MIT-LICENSE | 20 ++ .../rails/plugin_new/templates/README.rdoc | 3 + .../rails/plugin_new/templates/Rakefile | 46 ++++ .../rails/plugin_new/templates/gitignore | 6 + .../plugin_new/templates/lib/%name%.rb.tt | 2 + .../plugin_new/templates/rails/application.rb | 12 + .../rails/plugin_new/templates/rails/boot.rb | 10 + .../plugin_new/templates/script/rails.tt | 5 + .../templates/test/%name%_test.rb.tt | 7 + .../test/integration/navigation_test.rb.tt | 7 + .../test/support/integration_case.rb | 5 + .../plugin_new/templates/test/test_helper.rb | 22 ++ .../lib/plugin_builders/empty_builder.rb | 2 + .../lib/plugin_builders/simple_builder.rb | 7 + .../lib/plugin_builders/tweak_builder.rb | 7 + .../generators/plugin_new_generator_test.rb | 179 ++++++++++++++ 21 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 railties/lib/rails/commands/plugin_new.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/Gemfile create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/Rakefile create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/gitignore create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb create mode 100644 railties/test/fixtures/lib/plugin_builders/empty_builder.rb create mode 100644 railties/test/fixtures/lib/plugin_builders/simple_builder.rb create mode 100644 railties/test/fixtures/lib/plugin_builders/tweak_builder.rb create mode 100644 railties/test/generators/plugin_new_generator_test.rb diff --git a/railties/lib/rails/cli.rb b/railties/lib/rails/cli.rb index 1260772605..c8d70d8ffa 100644 --- a/railties/lib/rails/cli.rb +++ b/railties/lib/rails/cli.rb @@ -11,4 +11,9 @@ $:.unshift(railties_path) if File.directory?(railties_path) && !$:.include?(rail require 'rails/ruby_version_check' Signal.trap("INT") { puts; exit } -require 'rails/commands/application' +if ARGV.first == 'plugin' + ARGV.shift + require 'rails/commands/plugin_new' +else + require 'rails/commands/application' +end diff --git a/railties/lib/rails/commands/plugin_new.rb b/railties/lib/rails/commands/plugin_new.rb new file mode 100644 index 0000000000..00a7e30902 --- /dev/null +++ b/railties/lib/rails/commands/plugin_new.rb @@ -0,0 +1,16 @@ +require 'rails/version' +if %w(--version -v).include? ARGV.first + puts "Rails #{Rails::VERSION::STRING}" + exit(0) +end + +if ARGV.first != "new" + ARGV[0] = "--help" +else + ARGV.shift +end + +require 'rails/generators' +require 'rails/generators/rails/plugin_new/plugin_new_generator' + +Rails::Generators::PluginNewGenerator.start diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb new file mode 100644 index 0000000000..239115c07d --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -0,0 +1,225 @@ +require "rails/generators/rails/app/app_generator" + +module Rails + class PluginBuilder + def rakefile + template "Rakefile" + end + + def readme + copy_file "README.rdoc" + end + + def gemfile + template "Gemfile" + end + + def license + template "MIT-LICENSE" + end + + def gemspec + template "%name%.gemspec" + end + + def gitignore + copy_file "gitignore", ".gitignore" + end + + def lib + directory "lib" + end + + def test + directory "test" + end + + def test_dummy + invoke Rails::Generators::AppGenerator, + [ File.expand_path(dummy_path, destination_root) ] + end + + def test_dummy_config + store_application_definition! + template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true + template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true + end + + def test_dummy_clean + inside dummy_path do + remove_file ".gitignore" + remove_file "db/seeds.rb" + remove_file "doc" + remove_file "Gemfile" + remove_file "lib/tasks" + remove_file "public/images/rails.png" + remove_file "public/index.html" + remove_file "public/robots.txt" + remove_file "README" + remove_file "test" + remove_file "vendor" + end + end + + def script + directory "script" do |content| + "#{shebang}\n" + content + end + chmod "script", 0755, :verbose => false + end + end + + module Generators + class PluginNewGenerator < Base + attr_accessor :rails_template + + add_shebang_option! + + argument :plugin_path, :type => :string + + class_option :builder, :type => :string, :aliases => "-b", + :desc => "Path to a plugin builder (can be a filesystem path or URL)" + + class_option :skip_gemfile, :type => :boolean, :default => false, + :desc => "Don't create a Gemfile" + + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" + + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, + :desc => "Show this help message and quit" + + def self.say_step(message) + @step = (@step || 0) + 1 + class_eval <<-METHOD, __FILE__, __LINE__ + 1 + def step_#{@step} + #{"puts" if @step > 1} + say_status "STEP #{@step}", #{message.inspect} + end + METHOD + end + + def initialize(*args) + raise Error, "Options should be given after plugin name. For details run: rails plugin --help" if args[0].blank? + + @original_wd = Dir.pwd + + super + end + + say_step "Creating gem skeleton" + + def create_root + self.destination_root = File.expand_path(plugin_path, destination_root) + valid_plugin_const? + + empty_directory '.' + FileUtils.cd(destination_root) unless options[:pretend] + end + + def create_root_files + build(:readme) + build(:rakefile) + build(:gemspec) + build(:license) + build(:gitignore) unless options[:skip_git] + build(:gemfile) unless options[:skip_gemfile] + end + + def create_config_files + build(:config) + end + + def create_lib_files + build(:lib) + end + + def create_script_files + build(:script) + end + + def create_test_files + build(:test) unless options[:skip_test_unit] + end + + say_step "Vendoring Rails application at test/dummy" + + def create_test_dummy_files + build(:test_dummy) + end + + say_step "Configuring Rails application" + + def change_config_files + build(:test_dummy_config) + end + + say_step "Removing unneeded files" + + def remove_uneeded_rails_files + build(:test_dummy_clean) + end + + protected + + def self.banner + "rails plugin 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?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder + 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 name + @name ||= File.basename(destination_root) + end + + def camelized + @camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize + end + + def valid_plugin_const? + if camelized =~ /^\d/ + raise Error, "Invalid plugin name #{name}. Please give a name which does not start with numbers." + elsif RESERVED_NAMES.include?(name) + raise Error, "Invalid plugin name #{name}. Please give a name which does not match one of the reserved rails words." + elsif Object.const_defined?(camelized) + raise Error, "Invalid plugin name #{name}, constant #{camelized} is already in use. Please choose another application name." + end + end + + def dummy_path + "test/dummy" + end + + def application_definition + @application_definition ||= begin + unless options[:pretend] + contents = File.read(File.expand_path("#{dummy_path}/config/application.rb", destination_root)) + contents[(contents.index("module Dummy"))..-1] + end + end + end + alias :store_application_definition! :application_definition + end + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec new file mode 100644 index 0000000000..3d9bfb22c7 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec @@ -0,0 +1,9 @@ +# Provide a simple gemspec so you can easily use your +# project in your rails apps through git. +Gem::Specification.new do |s| + s.name = "<%= name %>" + s.summary = "Insert <%= camelized %> summary." + s.description = "Insert <%= camelized %> description." + s.files = Dir["lib/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"] + s.version = "0.0.1" +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile new file mode 100644 index 0000000000..83ff86bbd8 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -0,0 +1,11 @@ +source "http://rubygems.org" + +gem "rails", :git => "http://github.com/rails/rails.git" +gem "arel" , :git => "http://github.com/rails/arel.git" +gem "rack" , :git => "http://github.com/rack/rack.git" +gem "capybara", ">= 0.3.9" +gem "sqlite3-ruby", :require => "sqlite3" + +if RUBY_VERSION < '1.9' + gem "ruby-debug", ">= 0.10.3" +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE b/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE new file mode 100644 index 0000000000..d7a9109894 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright <%= Date.today.year %> YOURNAME + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc b/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc new file mode 100644 index 0000000000..301d647731 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/README.rdoc @@ -0,0 +1,3 @@ += <%= camelized %> + +This project rocks and uses MIT-LICENSE. \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile new file mode 100644 index 0000000000..c0e6185ddc --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -0,0 +1,46 @@ +# encoding: UTF-8 +require 'rubygems' +begin + require 'bundler/setup' +rescue LoadError + puts 'You must `gem install bundler` and `bundle install` to run rake tasks' +end + +require 'rake' +require 'rake/rdoctask' +require 'rake/gempackagetask' + +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + +task :default => :test + +Rake::RDocTask.new(:rdoc) do |rdoc| + rdoc.rdoc_dir = 'rdoc' + rdoc.title = '<%= camelized %>' + rdoc.options << '--line-numbers' << '--inline-source' + rdoc.rdoc_files.include('README.rdoc') + rdoc.rdoc_files.include('lib/**/*.rb') +end + +spec = Gem::Specification.new do |s| + s.name = "<%= name %>" + s.summary = "Insert <%= camelized %> summary." + s.description = "Insert <%= camelized %> description." + s.files = FileList["[A-Z]*", "lib/**/*"] + s.version = "0.0.1" +end + +Rake::GemPackageTask.new(spec) do |pkg| +end + +desc "Install the gem #{spec.name}-#{spec.version}.gem" +task :install do + system("gem install pkg/#{spec.name}-#{spec.version}.gem --no-ri --no-rdoc") +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/gitignore b/railties/lib/rails/generators/rails/plugin_new/templates/gitignore new file mode 100644 index 0000000000..1463de6dfb --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/gitignore @@ -0,0 +1,6 @@ +.bundle/ +log/*.log +pkg/ +test/dummy/db/*.sqlite3 +test/dummy/log/*.log +test/dummy/tmp/ \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt new file mode 100644 index 0000000000..cf77a0b4d3 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt @@ -0,0 +1,2 @@ +module <%= camelized %> +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb new file mode 100644 index 0000000000..fee63ea83e --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb @@ -0,0 +1,12 @@ +require File.expand_path('../boot', __FILE__) + +require "active_model/railtie" +require "active_record/railtie" +require "action_controller/railtie" +require "action_view/railtie" +require "action_mailer/railtie" + +Bundler.require +require "<%= name %>" + +<%= application_definition %> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb b/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb new file mode 100644 index 0000000000..eba0681370 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/boot.rb @@ -0,0 +1,10 @@ +require 'rubygems' +gemfile = File.expand_path('../../../../Gemfile', __FILE__) + +if File.exist?(gemfile) + ENV['BUNDLE_GEMFILE'] = gemfile + require 'bundler' + Bundler.setup +end + +$:.unshift File.expand_path('../../../../lib', __FILE__) \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt new file mode 100644 index 0000000000..cd4f7f6ab3 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby +# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. + +ENGINE_PATH = File.expand_path('../..', __FILE__) +load File.expand_path('../../test/dummy/script/rails', __FILE__) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt new file mode 100644 index 0000000000..0a8bbd4aaf --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt @@ -0,0 +1,7 @@ +require 'test_helper' + +class <%= camelized %>Test < ActiveSupport::TestCase + test "truth" do + assert_kind_of Module, <%= camelized %> + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt new file mode 100644 index 0000000000..42721899c8 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt @@ -0,0 +1,7 @@ +require 'test_helper' + +class NagivationTest < ActiveSupport::IntegrationCase + test "truth" do + assert_kind_of Dummy::Application, Rails.application + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb new file mode 100644 index 0000000000..4cfe3f0e71 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb @@ -0,0 +1,5 @@ +# Define a bare test case to use with Capybara +class ActiveSupport::IntegrationCase < ActiveSupport::TestCase + include Capybara + include Rails.application.routes.url_helpers +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb new file mode 100644 index 0000000000..5c39780a23 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -0,0 +1,22 @@ +# Configure Rails Envinronment +ENV["RAILS_ENV"] = "test" + +require File.expand_path("../dummy/config/environment.rb", __FILE__) +require "rails/test_help" + +ActionMailer::Base.delivery_method = :test +ActionMailer::Base.perform_deliveries = true +ActionMailer::Base.default_url_options[:host] = "test.com" + +Rails.backtrace_cleaner.remove_silencers! + +# Configure capybara for integration testing +require "capybara/rails" +Capybara.default_driver = :rack_test +Capybara.default_selector = :css + +# Run any available migration +ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) + +# Load support files +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } \ No newline at end of file diff --git a/railties/test/fixtures/lib/plugin_builders/empty_builder.rb b/railties/test/fixtures/lib/plugin_builders/empty_builder.rb new file mode 100644 index 0000000000..5c5607621c --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/empty_builder.rb @@ -0,0 +1,2 @@ +class PluginBuilder +end diff --git a/railties/test/fixtures/lib/plugin_builders/simple_builder.rb b/railties/test/fixtures/lib/plugin_builders/simple_builder.rb new file mode 100644 index 0000000000..08f6c5535d --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/simple_builder.rb @@ -0,0 +1,7 @@ +class PluginBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb b/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb new file mode 100644 index 0000000000..1e801409a4 --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/tweak_builder.rb @@ -0,0 +1,7 @@ +class PluginBuilder < Rails::PluginBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb new file mode 100644 index 0000000000..3c38dffce2 --- /dev/null +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -0,0 +1,179 @@ +require 'abstract_unit' +require 'generators/generators_test_helper' +require 'rails/generators/rails/plugin_new/plugin_new_generator' + +DEFAULT_PLUGIN_FILES = %w( + .gitignore + Gemfile + Rakefile + bukkits.gemspec + MIT-LICENSE + lib + lib/bukkits.rb + script/rails + test/bukkits_test.rb + test/integration/navigation_test.rb + test/support/integration_case.rb + test/test_helper.rb + test/dummy +) + + +class PluginNewGeneratorTest < Rails::Generators::TestCase + include GeneratorsTestHelper + destination File.join(Rails.root, "tmp/bukkits") + arguments [destination_root] + + def setup + Rails.application = TestApp::Application + super + @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + + Kernel::silence_warnings do + Thor::Base.shell.send(:attr_accessor, :always_force) + @shell = Thor::Base.shell.new + @shell.send(:always_force=, true) + end + end + + def teardown + super + Rails.application = TestApp::Application.instance + end + + def test_plugin_skeleton_is_created + run_generator + + DEFAULT_PLUGIN_FILES.each{ |path| assert_file path } + end + + def test_plugin_new_generate_pretend + run_generator ["testapp", "--pretend"] + + DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path } + end + + def test_options_before_plugin_name_raises_an_error + content = capture(:stderr){ run_generator(["--pretend", destination_root]) } + assert_equal "Options should be given after plugin name. For details run: rails plugin --help\n", content + end + + def test_name_collision_raises_an_error + reserved_words = %w[application destroy plugin runner test] + reserved_words.each do |reserved| + content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } + assert_equal "Invalid plugin name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content + end + end + + def test_invalid_plugin_name_raises_an_error + content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] } + assert_equal "Invalid plugin name 43-things. Please give a name which does not start with numbers.\n", content + end + + def test_plugin_name_raises_an_error_if_name_already_used_constant + %w{ String Hash Class Module Set Symbol }.each do |ruby_class| + content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } + assert_equal "Invalid plugin name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content + end + end + + def test_invalid_plugin_name_is_fixed + run_generator [File.join(destination_root, "things-43")] + assert_file "things-43/lib/things-43.rb", /module Things43/ + end + + def test_shebang_is_added_to_rails_file + run_generator [destination_root, "--ruby", "foo/bar/baz"] + assert_file "script/rails", /#!foo\/bar\/baz/ + end + + def test_shebang_when_is_the_same_as_default_use_env + run_generator [destination_root, "--ruby", Thor::Util.ruby_command] + assert_file "script/rails", /#!\/usr\/bin\/env/ + end + + def test_generating_test_files + run_generator + assert_file "test/test_helper.rb" + assert_directory "test/support/" + assert_directory "test/integration/" + + assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ + assert_file "test/integration/navigation_test.rb", /assert_kind_of Dummy::Application, Rails.application/ + assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/ + end + +protected + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end + +end + +class CustomPluginGeneratorTest < Rails::Generators::TestCase + include GeneratorsTestHelper + tests Rails::Generators::PluginNewGenerator + + destination File.join(Rails.root, "tmp/bukkits") + arguments [destination_root] + + def setup + Rails.application = TestApp::Application + super + @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + end + + def teardown + super + Object.class_eval { remove_const :PluginBuilder if const_defined?(:PluginBuilder) } + Rails.application = TestApp::Application.instance + end + + def test_builder_option_with_empty_app_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/empty_builder.rb"]) + DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path } + end + + def test_builder_option_with_simple_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/simple_builder.rb"]) + (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + 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/plugin_builders/simple_builder.rb"]) + FileUtils.cd(destination_root) + (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_tweak_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/tweak_builder.rb"]) + DEFAULT_PLUGIN_FILES.each{ |path| assert_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_http + path = "http://gist.github.com/103208.txt" + template = "class PluginBuilder; 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_PLUGIN_FILES.each{ |path| assert_no_file path } + end + +protected + + def action(*args, &block) + silence(:stdout){ generator.send(*args, &block) } + end +end From b37938eff72fe370ddc84afb656f6b4775053f6a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 19 Oct 2010 23:26:48 +0200 Subject: [PATCH 02/36] Refactored AppGenerator and PluginNewGenerator to inherit from AppBase. --- railties/lib/rails/generators/app_base.rb | 61 +++++++++++++++++++ .../generators/rails/app/app_generator.rb | 25 +++----- .../rails/plugin_new/plugin_new_generator.rb | 50 +++------------ 3 files changed, 79 insertions(+), 57 deletions(-) create mode 100644 railties/lib/rails/generators/app_base.rb diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb new file mode 100644 index 0000000000..d66b1345c1 --- /dev/null +++ b/railties/lib/rails/generators/app_base.rb @@ -0,0 +1,61 @@ +require 'digest/md5' +require 'active_support/secure_random' +require 'rails/version' unless defined?(Rails::VERSION) +require 'rbconfig' +require 'open-uri' +require 'uri' + +module Rails + module Generators + class AppBase < Base + def self.say_step(message) + @step = (@step || 0) + 1 + class_eval <<-METHOD, __FILE__, __LINE__ + 1 + def step_#{@step} + #{"puts" if @step > 1} + say_status "STEP #{@step}", #{message.inspect} + end + METHOD + end + + def initialize(*args) + @original_wd = Dir.pwd + + super + end + + protected + + 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 = get_builder_class + 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 create_root + self.destination_root = File.expand_path(app_path, destination_root) + valid_const? + + empty_directory '.' + FileUtils.cd(destination_root) unless options[:pretend] + end + end + end +end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 44f9fde0a6..16150c306a 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -1,9 +1,4 @@ -require 'digest/md5' -require 'active_support/secure_random' -require 'rails/version' unless defined?(Rails::VERSION) -require 'rbconfig' -require 'open-uri' -require 'uri' +require 'rails/generators/app_base' module Rails module ActionMethods @@ -158,7 +153,7 @@ module Rails RESERVED_NAMES = %w[application destroy benchmarker profiler plugin runner test] - class AppGenerator < Base + class AppGenerator < AppBase DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) JAVASCRIPTS = %w( prototype jquery ) @@ -210,8 +205,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 if !options[:skip_active_record] && !DATABASES.include?(options[:database]) @@ -224,12 +217,8 @@ module Rails end def create_root - self.destination_root = File.expand_path(app_path, destination_root) - valid_app_const? - - empty_directory '.' set_default_accessors! - FileUtils.cd(destination_root) unless options[:pretend] + super end def create_root_files @@ -339,7 +328,7 @@ module Rails instance_eval(&prok) end - builder_class = defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder + builder_class = get_builder_class builder_class.send(:include, ActionMethods) builder_class.new(self) end @@ -388,7 +377,7 @@ module Rails @app_const ||= "#{app_const_base}::Application" end - def valid_app_const? + def valid_const? if app_const =~ /^\d/ raise Error, "Invalid application name #{app_name}. Please give a name which does not start with numbers." elsif RESERVED_NAMES.include?(app_name) @@ -442,6 +431,10 @@ module Rails empty_directory(destination, config) create_file("#{destination}/.gitkeep") unless options[:skip_git] end + + def get_builder_class + defined?(::AppBuilder) ? ::AppBuilder : Rails::AppBuilder + end end end end diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 239115c07d..9ee7edfc2b 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -1,3 +1,4 @@ +require 'rails/generators/app_base' require "rails/generators/rails/app/app_generator" module Rails @@ -70,12 +71,13 @@ module Rails end module Generators - class PluginNewGenerator < Base + class PluginNewGenerator < AppBase attr_accessor :rails_template add_shebang_option! argument :plugin_path, :type => :string + alias_method :app_path, :plugin_path class_option :builder, :type => :string, :aliases => "-b", :desc => "Path to a plugin builder (can be a filesystem path or URL)" @@ -89,32 +91,17 @@ module Rails class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, :desc => "Show this help message and quit" - def self.say_step(message) - @step = (@step || 0) + 1 - class_eval <<-METHOD, __FILE__, __LINE__ + 1 - def step_#{@step} - #{"puts" if @step > 1} - say_status "STEP #{@step}", #{message.inspect} - end - METHOD - end def initialize(*args) raise Error, "Options should be given after plugin name. For details run: rails plugin --help" if args[0].blank? - @original_wd = Dir.pwd - super end say_step "Creating gem skeleton" def create_root - self.destination_root = File.expand_path(plugin_path, destination_root) - valid_plugin_const? - - empty_directory '.' - FileUtils.cd(destination_root) unless options[:pretend] + super end def create_root_files @@ -166,29 +153,6 @@ module Rails "rails plugin 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?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder - 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 name @name ||= File.basename(destination_root) end @@ -197,7 +161,7 @@ module Rails @camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize end - def valid_plugin_const? + def valid_const? if camelized =~ /^\d/ raise Error, "Invalid plugin name #{name}. Please give a name which does not start with numbers." elsif RESERVED_NAMES.include?(name) @@ -220,6 +184,10 @@ module Rails end end alias :store_application_definition! :application_definition + + def get_builder_class + defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder + end end end end From b8a0fabe184f6c8f926f7869341ca40b6395606a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 00:47:13 +0200 Subject: [PATCH 03/36] Ensure that options for plugin new generator are not passed to application generator --- .../generators/rails/plugin_new/plugin_new_generator.rb | 2 +- railties/test/generators/plugin_new_generator_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 9ee7edfc2b..06ef158a51 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -37,7 +37,7 @@ module Rails def test_dummy invoke Rails::Generators::AppGenerator, - [ File.expand_path(dummy_path, destination_root) ] + [ File.expand_path(dummy_path, destination_root) ], {} end def test_dummy_config diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 3c38dffce2..fa00e75132 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -104,6 +104,12 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/ end + def test_ensure_that_plugin_options_are_not_passed_app_generator + output = run_generator [destination_root, "--skip_gemfile"] + assert_no_file "Gemfile" + assert_match /STEP 2.*create Gemfile/m, output + end + protected def action(*args, &block) From bcd414fd10a0e401cfb1de95cc9b2940b1df0ff6 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 01:05:34 +0200 Subject: [PATCH 04/36] Add support for templates for rails plugin new --- railties/lib/rails/generators/app_base.rb | 18 +++++++++++++++++ .../generators/rails/app/app_generator.rb | 16 +-------------- .../rails/plugin_new/plugin_new_generator.rb | 11 ++++++++++ .../generators/plugin_new_generator_test.rb | 20 +++++++++++++++++++ 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index d66b1345c1..ecaf92c683 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -54,8 +54,26 @@ module Rails valid_const? empty_directory '.' + set_default_accessors! FileUtils.cd(destination_root) unless options[:pretend] end + + def apply_rails_template + apply rails_template if rails_template + rescue Thor::Error, LoadError, Errno::ENOENT => e + raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}" + end + + def set_default_accessors! + self.rails_template = case options[:template] + when /^http:\/\// + options[:template] + when String + File.expand_path(options[:template], Dir.pwd) + else + options[:template] + end + end end end end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 16150c306a..8c6ec41e4d 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -217,7 +217,6 @@ module Rails end def create_root - set_default_accessors! super end @@ -299,9 +298,7 @@ module Rails end def apply_rails_template - apply rails_template if rails_template - rescue Thor::Error, LoadError, Errno::ENOENT => e - raise Error, "The template [#{rails_template}] could not be loaded. Error: #{e}" + super end def bundle_if_dev_or_edge @@ -338,17 +335,6 @@ module Rails builder.send(meth, *args) if builder.respond_to?(meth) end - def set_default_accessors! - self.rails_template = case options[:template] - when /^http:\/\// - options[:template] - when String - File.expand_path(options[:template], Dir.pwd) - else - options[:template] - end - end - # Define file as an alias to create_file for backwards compatibility. def file(*args, &block) create_file(*args, &block) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 06ef158a51..9785a6938a 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -82,6 +82,9 @@ module Rails class_option :builder, :type => :string, :aliases => "-b", :desc => "Path to a plugin 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)" + class_option :skip_gemfile, :type => :boolean, :default => false, :desc => "Don't create a Gemfile" @@ -147,6 +150,14 @@ module Rails build(:test_dummy_clean) end + def finish_template + build(:leftovers) + end + + def apply_rails_template + super + end + protected def self.banner diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index fa00e75132..f3672cb6f1 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -110,6 +110,26 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_match /STEP 2.*create Gemfile/m, output end + def test_template_from_dir_pwd + FileUtils.cd(Rails.root) + assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } + assert_match /The template \[.*\] could not be loaded/, content + assert_match /non\/existant\/path/, content + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + template = %{ say "It works!" } + template.instance_eval "def read; self; end" # Make the string respond to read + + generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + assert_match /It works!/, silence(:stdout){ generator.invoke_all } + end + protected def action(*args, &block) From bbf02ffea449b32c93e931f7ff2625a8dc736792 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 01:08:21 +0200 Subject: [PATCH 05/36] That method is already declared at AppBase --- .../generators/rails/app/app_generator.rb | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 8c6ec41e4d..9328cdc789 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -312,29 +312,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 = get_builder_class - 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 - # Define file as an alias to create_file for backwards compatibility. def file(*args, &block) create_file(*args, &block) From 5c8b48ab4b9d08f3e38087214635918e659d72b6 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 06:19:11 +0200 Subject: [PATCH 06/36] Added USAGE for rails plugin new --- railties/lib/rails/generators/rails/plugin_new/USAGE | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 railties/lib/rails/generators/rails/plugin_new/USAGE diff --git a/railties/lib/rails/generators/rails/plugin_new/USAGE b/railties/lib/rails/generators/rails/plugin_new/USAGE new file mode 100644 index 0000000000..9a7bf9f396 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/USAGE @@ -0,0 +1,10 @@ +Description: + The 'rails plugin new' command creates a skeleton for developing any + kind of Rails extension with ability to run tests using dummy Rails + application. + +Example: + rails plugin new ~/Code/Ruby/blog + + This generates a skeletal Rails plugin in ~/Code/Ruby/blog. + See the README in the newly created plugin to get going. From e51e9e2db0359355feef71e735a1f9cb764ec929 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 07:59:28 +0200 Subject: [PATCH 07/36] Add --dev and --edge options to rails plugin new --- railties/lib/rails/generators/app_base.rb | 34 +++++++++++++++++++ .../generators/rails/app/app_generator.rb | 7 +--- .../generators/rails/app/templates/Gemfile | 17 +--------- .../rails/plugin_new/plugin_new_generator.rb | 10 ++++++ .../rails/plugin_new/templates/Gemfile | 5 ++- .../generators/plugin_new_generator_test.rb | 13 +++++++ 6 files changed, 61 insertions(+), 25 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index ecaf92c683..e0f0242da8 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -74,6 +74,40 @@ module Rails options[:template] end end + + def rails_gemfile_entry + if options.dev? + <<-GEMFILE +gem 'rails', :path => '#{Rails::Generators::RAILS_DEV_PATH}' +gem 'arel', :git => 'git://github.com/rails/arel.git' +gem "rack", :git => "git://github.com/rack/rack.git" + GEMFILE + elsif options.edge? + <<-GEMFILE +gem 'rails', :git => 'git://github.com/rails/rails.git' +gem 'arel', :git => 'git://github.com/rails/arel.git' +gem "rack", :git => "git://github.com/rack/rack.git" + GEMFILE + else + <<-GEMFILE +gem 'rails', '#{Rails::VERSION::STRING}' + +# Bundle edge Rails instead: +# gem 'rails', :git => 'git://github.com/rails/rails.git' +# gem 'arel', :git => 'git://github.com/rails/arel.git' +# gem "rack", :git => "git://github.com/rack/rack.git" + GEMFILE + end + end + + def bundle_if_dev_or_edge + bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') + run "#{bundle_command} install" if dev_or_edge? + end + + def dev_or_edge? + options.dev? || options.edge? + end end end end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 9328cdc789..7c89eabedd 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -302,8 +302,7 @@ module Rails end def bundle_if_dev_or_edge - bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - run "#{bundle_command} install" if dev_or_edge? + super end protected @@ -354,10 +353,6 @@ module Rails ActiveSupport::SecureRandom.hex(64) end - def dev_or_edge? - options.dev? || options.edge? - end - def gem_for_database # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) case options[:database] diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 40213b1261..4a37f675ad 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -1,21 +1,6 @@ source 'http://rubygems.org' -<%- if options.dev? -%> -gem 'rails', :path => '<%= Rails::Generators::RAILS_DEV_PATH %>' -gem 'arel', :git => 'git://github.com/rails/arel.git' -gem "rack", :git => "git://github.com/rack/rack.git" -<%- elsif options.edge? -%> -gem 'rails', :git => 'git://github.com/rails/rails.git' -gem 'arel', :git => 'git://github.com/rails/arel.git' -gem "rack", :git => "git://github.com/rack/rack.git" -<%- else -%> -gem 'rails', '<%= Rails::VERSION::STRING %>' - -# Bundle edge Rails instead: -# gem 'rails', :git => 'git://github.com/rails/rails.git' -# gem 'arel', :git => 'git://github.com/rails/arel.git' -# gem "rack", :git => "git://github.com/rack/rack.git" -<%- end -%> +<%= rails_gemfile_entry -%> <% unless options[:skip_active_record] -%> gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= require_for_database %>'<% end %> diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 9785a6938a..3c710b8908 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -91,6 +91,12 @@ module Rails class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, :desc => "Skip Git ignores and keeps" + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the plugin with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the plugin with Gemfile pointing to Rails repository" + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, :desc => "Show this help message and quit" @@ -158,6 +164,10 @@ module Rails super end + def bundle_if_dev_or_edge + super + end + protected def self.banner diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 83ff86bbd8..899a9366d3 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -1,8 +1,7 @@ source "http://rubygems.org" -gem "rails", :git => "http://github.com/rails/rails.git" -gem "arel" , :git => "http://github.com/rails/arel.git" -gem "rack" , :git => "http://github.com/rack/rack.git" +<%= rails_gemfile_entry -%> + gem "capybara", ">= 0.3.9" gem "sqlite3-ruby", :require => "sqlite3" diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index f3672cb6f1..638ff8dce5 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -130,6 +130,19 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_match /It works!/, silence(:stdout){ generator.invoke_all } end + def test_dev_option + generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + rails_path = File.expand_path('../../..', Rails.root) + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ + end + + def test_edge_option + generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/ + end + protected def action(*args, &block) From 59d52229f9ddd55a1cf0674c774a8aeb68300ccf Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 20:45:21 +0200 Subject: [PATCH 08/36] Change // style regexp to %r{}, to not confuse editors code highlighting --- railties/test/generators/plugin_new_generator_test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 638ff8dce5..8f230525bc 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -140,7 +140,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_edge_option generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") silence(:stdout){ generator.invoke_all } - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/ + assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} end protected From fd1562af8c662fee8a44d244eaed3350ce10e7da Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 21:21:37 +0200 Subject: [PATCH 09/36] Ensure that tests run properly --- railties/test/generators/plugin_new_generator_test.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 8f230525bc..0d88d36971 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -143,6 +143,13 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} end + def test_ensure_that_tests_works + run_generator + FileUtils.cd destination_root + `bundle install` + assert_match /2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test` + end + protected def action(*args, &block) From b36fa51a3f56431d8e46c1fff6a6493d3c10607a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Oct 2010 21:21:14 +0200 Subject: [PATCH 10/36] Allow easy overriding of test framework in 'rake plugin new' generator, using PluginBuilder --- .../rails/plugin_new/plugin_new_generator.rb | 35 +++++++++++++++---- .../rails/plugin_new/templates/Rakefile | 11 ++---- .../plugin_new/templates/script/rails.tt | 2 +- .../lib/plugin_builders/spec_builder.rb | 13 +++++++ .../generators/plugin_new_generator_test.rb | 10 ++++++ 5 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 railties/test/fixtures/lib/plugin_builders/spec_builder.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 3c710b8908..6067c5d87e 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -35,7 +35,7 @@ module Rails directory "test" end - def test_dummy + def generate_test_dummy invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], {} end @@ -68,6 +68,27 @@ module Rails end chmod "script", 0755, :verbose => false end + + def rakefile_test_tasks + <<-RUBY +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + RUBY + end + + def dummy_path + "#{test_path}/dummy" + end + + def test_path + "test" + end end module Generators @@ -141,7 +162,7 @@ module Rails say_step "Vendoring Rails application at test/dummy" def create_test_dummy_files - build(:test_dummy) + build(:generate_test_dummy) end say_step "Configuring Rails application" @@ -192,10 +213,6 @@ module Rails end end - def dummy_path - "test/dummy" - end - def application_definition @application_definition ||= begin unless options[:pretend] @@ -209,6 +226,12 @@ module Rails def get_builder_class defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder end + + [:test_path, :dummy_path, :rakefile_test_tasks].each do |name| + define_method name do + builder.send(name) if builder.respond_to?(name) + end + end end end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile index c0e6185ddc..af5f672396 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -10,16 +10,9 @@ require 'rake' require 'rake/rdoctask' require 'rake/gempackagetask' -require 'rake/testtask' +<%= rakefile_test_tasks %> -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.libs << 'test' - t.pattern = 'test/**/*_test.rb' - t.verbose = false -end - -task :default => :test +task :default => :<%= test_path %> Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt index cd4f7f6ab3..91d9cf079d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt +++ b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt @@ -2,4 +2,4 @@ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. ENGINE_PATH = File.expand_path('../..', __FILE__) -load File.expand_path('../../test/dummy/script/rails', __FILE__) +load File.expand_path('../../<%= test_path %>/dummy/script/rails', __FILE__) diff --git a/railties/test/fixtures/lib/plugin_builders/spec_builder.rb b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb new file mode 100644 index 0000000000..bdaa1fb8e1 --- /dev/null +++ b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb @@ -0,0 +1,13 @@ +class PluginBuilder < Rails::PluginBuilder + def test + create_file "spec/spec_helper.rb" + end + + def test_path + "spec" + end + + def rakefile_test_tasks + "# spec tasks in rakefile" + end +end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 0d88d36971..a7177914e1 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -217,6 +217,16 @@ class CustomPluginGeneratorTest < Rails::Generators::TestCase DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path } end + def test_overriding_test_framework + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/spec_builder.rb"]) + assert_file 'spec/spec_helper.rb' + assert_file 'Rakefile', /task :default => :spec/ + assert_file 'Rakefile', /# spec tasks in rakefile/ + assert_file 'spec/dummy' + assert_file 'script/rails', %r{spec/dummy} + end + protected def action(*args, &block) From ae1debd442113ed9476e776fe27cd95730896b59 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 21 Oct 2010 00:55:08 +0200 Subject: [PATCH 11/36] Make tests for app and plugin generators more DRY --- .../rails/plugin_new/plugin_new_generator.rb | 2 +- .../lib/{ => app_builders}/empty_builder.rb | 0 .../lib/app_builders/simple_builder.rb | 7 + .../lib/app_builders/tweak_builder.rb | 7 + railties/test/fixtures/lib/simple_builder.rb | 7 - railties/test/fixtures/lib/tweak_builder.rb | 7 - .../test/generators/app_generator_test.rb | 156 ++------------- .../generators/plugin_new_generator_test.rb | 153 ++------------- .../test/generators/shared_generator_tests.rb | 177 ++++++++++++++++++ 9 files changed, 224 insertions(+), 292 deletions(-) rename railties/test/fixtures/lib/{ => app_builders}/empty_builder.rb (100%) create mode 100644 railties/test/fixtures/lib/app_builders/simple_builder.rb create mode 100644 railties/test/fixtures/lib/app_builders/tweak_builder.rb delete mode 100644 railties/test/fixtures/lib/simple_builder.rb delete mode 100644 railties/test/fixtures/lib/tweak_builder.rb create mode 100644 railties/test/generators/shared_generator_tests.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 6067c5d87e..8296f37211 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -123,7 +123,7 @@ end def initialize(*args) - raise Error, "Options should be given after plugin name. For details run: rails plugin --help" if args[0].blank? + raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? super end diff --git a/railties/test/fixtures/lib/empty_builder.rb b/railties/test/fixtures/lib/app_builders/empty_builder.rb similarity index 100% rename from railties/test/fixtures/lib/empty_builder.rb rename to railties/test/fixtures/lib/app_builders/empty_builder.rb diff --git a/railties/test/fixtures/lib/app_builders/simple_builder.rb b/railties/test/fixtures/lib/app_builders/simple_builder.rb new file mode 100644 index 0000000000..993d3a2aa2 --- /dev/null +++ b/railties/test/fixtures/lib/app_builders/simple_builder.rb @@ -0,0 +1,7 @@ +class AppBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/app_builders/tweak_builder.rb b/railties/test/fixtures/lib/app_builders/tweak_builder.rb new file mode 100644 index 0000000000..cb50be01cb --- /dev/null +++ b/railties/test/fixtures/lib/app_builders/tweak_builder.rb @@ -0,0 +1,7 @@ +class AppBuilder < Rails::AppBuilder + def gitignore + create_file ".gitignore", <<-R.strip +foobar + R + end +end diff --git a/railties/test/fixtures/lib/simple_builder.rb b/railties/test/fixtures/lib/simple_builder.rb deleted file mode 100644 index 47dcdc0d96..0000000000 --- a/railties/test/fixtures/lib/simple_builder.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AppBuilder - def configru - create_file "config.ru", <<-R.strip -run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] } - R - end -end \ No newline at end of file diff --git a/railties/test/fixtures/lib/tweak_builder.rb b/railties/test/fixtures/lib/tweak_builder.rb deleted file mode 100644 index eed20ecc9b..0000000000 --- a/railties/test/fixtures/lib/tweak_builder.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AppBuilder < Rails::AppBuilder - def configru - create_file "config.ru", <<-R.strip -run proc { |env| [200, { "Content-Type" => "text/html" }, ["Hello World"]] } - R - end -end \ No newline at end of file diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index c7339cb8d2..1f0ef922cd 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'generators/generators_test_helper' require 'rails/generators/rails/app/app_generator' +require 'generators/shared_generator_tests.rb' DEFAULT_APP_FILES = %w( .gitignore @@ -40,36 +41,10 @@ DEFAULT_APP_FILES = %w( class AppGeneratorTest < Rails::Generators::TestCase include GeneratorsTestHelper arguments [destination_root] + include SharedGeneratorTests - 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') - - Kernel::silence_warnings do - Thor::Base.shell.send(:attr_accessor, :always_force) - @shell = Thor::Base.shell.new - @shell.send(:always_force=, true) - end - end - - def teardown - super - Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) - Rails.application = TestApp::Application.instance - end - - def test_application_skeleton_is_created - run_generator - - DEFAULT_APP_FILES.each{ |path| assert_file path } - end - - def test_application_generate_pretend - run_generator ["testapp", "--pretend"] - - DEFAULT_APP_FILES.each{ |path| assert_no_file path } + def default_files + ::DEFAULT_APP_FILES end def test_application_controller_and_layout_files @@ -78,19 +53,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_no_file "public/stylesheets/application.css" end - def test_options_before_application_name_raises_an_error - content = capture(:stderr){ run_generator(["--skip-active-record", destination_root]) } - assert_equal "Options should be given after the application name. For details run: rails --help\n", content - end - - def test_name_collision_raises_an_error - reserved_words = %w[application destroy plugin runner test] - reserved_words.each do |reserved| - content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } - assert_equal "Invalid application name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content - end - end - def test_invalid_database_option_raises_an_error content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) } assert_match /Invalid value for \-\-database option/, content @@ -101,13 +63,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_equal "Invalid application name 43-things. Please give a name which does not start with numbers.\n", content end - def test_application_name_raises_an_error_if_name_already_used_constant - %w{ String Hash Class Module Set Symbol }.each do |ruby_class| - content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } - assert_equal "Invalid application name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content - end - end - def test_invalid_application_name_is_fixed run_generator [File.join(destination_root, "things-43")] assert_file "things-43/config/environment.rb", /Things43::Application\.initialize!/ @@ -217,36 +172,11 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "public/javascripts/rails.js", /jQuery/ end - def test_shebang_is_added_to_rails_file - run_generator [destination_root, "--ruby", "foo/bar/baz"] - assert_file "script/rails", /#!foo\/bar\/baz/ - end - - def test_shebang_when_is_the_same_as_default_use_env - run_generator [destination_root, "--ruby", Thor::Util.ruby_command] - assert_file "script/rails", /#!\/usr\/bin\/env/ - end - def test_template_from_dir_pwd FileUtils.cd(Rails.root) assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) end - def test_template_raises_an_error_with_invalid_path - content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } - assert_match /The template \[.*\] could not be loaded/, content - assert_match /non\/existant\/path/, content - end - - def test_template_is_executed_when_supplied - path = "http://gist.github.com/103208.txt" - template = %{ say "It works!" } - template.instance_eval "def read; self; end" # Make the string respond to read - - generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - assert_match /It works!/, silence(:stdout){ generator.invoke_all } - end - def test_usage_read_from_file File.expects(:read).returns("USAGE FROM FILE") assert_equal "USAGE FROM FILE", Rails::Generators::AppGenerator.desc @@ -266,19 +196,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file 'lib/test_file.rb', 'heres test data' end - def test_dev_option - generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - rails_path = File.expand_path('../../..', Rails.root) - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ - end - - def test_edge_option - generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$/ - end - protected def action(*args, &block) @@ -292,61 +209,20 @@ class CustomAppGeneratorTest < Rails::Generators::TestCase 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 + include SharedCustomGeneratorTests protected + def default_files + ::DEFAULT_APP_FILES + end + + def builders_dir + "app_builders" + end + + def builder_class + :AppBuilder + end def action(*args, &block) silence(:stdout){ generator.send(*args, &block) } diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index a7177914e1..e8a9c8ff51 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -1,6 +1,7 @@ require 'abstract_unit' require 'generators/generators_test_helper' require 'rails/generators/rails/plugin_new/plugin_new_generator' +require 'generators/shared_generator_tests.rb' DEFAULT_PLUGIN_FILES = %w( .gitignore @@ -23,47 +24,10 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase include GeneratorsTestHelper destination File.join(Rails.root, "tmp/bukkits") arguments [destination_root] + include SharedGeneratorTests - def setup - Rails.application = TestApp::Application - super - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - - Kernel::silence_warnings do - Thor::Base.shell.send(:attr_accessor, :always_force) - @shell = Thor::Base.shell.new - @shell.send(:always_force=, true) - end - end - - def teardown - super - Rails.application = TestApp::Application.instance - end - - def test_plugin_skeleton_is_created - run_generator - - DEFAULT_PLUGIN_FILES.each{ |path| assert_file path } - end - - def test_plugin_new_generate_pretend - run_generator ["testapp", "--pretend"] - - DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path } - end - - def test_options_before_plugin_name_raises_an_error - content = capture(:stderr){ run_generator(["--pretend", destination_root]) } - assert_equal "Options should be given after plugin name. For details run: rails plugin --help\n", content - end - - def test_name_collision_raises_an_error - reserved_words = %w[application destroy plugin runner test] - reserved_words.each do |reserved| - content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } - assert_equal "Invalid plugin name #{reserved}. Please give a name which does not match one of the reserved rails words.\n", content - end + def default_files + ::DEFAULT_PLUGIN_FILES end def test_invalid_plugin_name_raises_an_error @@ -71,28 +35,11 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_equal "Invalid plugin name 43-things. Please give a name which does not start with numbers.\n", content end - def test_plugin_name_raises_an_error_if_name_already_used_constant - %w{ String Hash Class Module Set Symbol }.each do |ruby_class| - content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } - assert_equal "Invalid plugin name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another application name.\n", content - end - end - def test_invalid_plugin_name_is_fixed run_generator [File.join(destination_root, "things-43")] assert_file "things-43/lib/things-43.rb", /module Things43/ end - def test_shebang_is_added_to_rails_file - run_generator [destination_root, "--ruby", "foo/bar/baz"] - assert_file "script/rails", /#!foo\/bar\/baz/ - end - - def test_shebang_when_is_the_same_as_default_use_env - run_generator [destination_root, "--ruby", Thor::Util.ruby_command] - assert_file "script/rails", /#!\/usr\/bin\/env/ - end - def test_generating_test_files run_generator assert_file "test/test_helper.rb" @@ -115,34 +62,6 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) end - def test_template_raises_an_error_with_invalid_path - content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } - assert_match /The template \[.*\] could not be loaded/, content - assert_match /non\/existant\/path/, content - end - - def test_template_is_executed_when_supplied - path = "http://gist.github.com/103208.txt" - template = %{ say "It works!" } - template.instance_eval "def read; self; end" # Make the string respond to read - - generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) - assert_match /It works!/, silence(:stdout){ generator.invoke_all } - end - - def test_dev_option - generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - rails_path = File.expand_path('../../..', Rails.root) - assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ - end - - def test_edge_option - generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") - silence(:stdout){ generator.invoke_all } - assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} - end - def test_ensure_that_tests_works run_generator FileUtils.cd destination_root @@ -164,58 +83,7 @@ class CustomPluginGeneratorTest < Rails::Generators::TestCase destination File.join(Rails.root, "tmp/bukkits") arguments [destination_root] - - def setup - Rails.application = TestApp::Application - super - @bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') - end - - def teardown - super - Object.class_eval { remove_const :PluginBuilder if const_defined?(:PluginBuilder) } - Rails.application = TestApp::Application.instance - end - - def test_builder_option_with_empty_app_builder - FileUtils.cd(destination_root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/empty_builder.rb"]) - DEFAULT_PLUGIN_FILES.each{ |path| assert_no_file path } - end - - def test_builder_option_with_simple_plugin_builder - FileUtils.cd(destination_root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/simple_builder.rb"]) - (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path } - assert_file ".gitignore", "foobar" - 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/plugin_builders/simple_builder.rb"]) - FileUtils.cd(destination_root) - (DEFAULT_PLUGIN_FILES - ['.gitignore']).each{ |path| assert_no_file path } - assert_file ".gitignore", "foobar" - end - - def test_builder_option_with_tweak_plugin_builder - FileUtils.cd(destination_root) - run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/tweak_builder.rb"]) - DEFAULT_PLUGIN_FILES.each{ |path| assert_file path } - assert_file ".gitignore", "foobar" - end - - def test_builder_option_with_http - path = "http://gist.github.com/103208.txt" - template = "class PluginBuilder; 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_PLUGIN_FILES.each{ |path| assert_no_file path } - end + include SharedCustomGeneratorTests def test_overriding_test_framework FileUtils.cd(destination_root) @@ -228,6 +96,17 @@ class CustomPluginGeneratorTest < Rails::Generators::TestCase end protected + def default_files + ::DEFAULT_PLUGIN_FILES + end + + def builder_class + :PluginBuilder + end + + def builders_dir + "plugin_builders" + end def action(*args, &block) silence(:stdout){ generator.send(*args, &block) } diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb new file mode 100644 index 0000000000..71cde6785c --- /dev/null +++ b/railties/test/generators/shared_generator_tests.rb @@ -0,0 +1,177 @@ +module SharedGeneratorTests + 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') + + Kernel::silence_warnings do + Thor::Base.shell.send(:attr_accessor, :always_force) + @shell = Thor::Base.shell.new + @shell.send(:always_force=, true) + end + end + + def teardown + super + Rails::Generators::AppGenerator.instance_variable_set('@desc', nil) + Rails.application = TestApp::Application.instance + end + + def test_skeleton_is_created + run_generator + + default_files.each{ |path| assert_file path } + end + + def test_plugin_new_generate_pretend + run_generator ["testapp", "--pretend"] + + default_files.each{ |path| assert_no_file path } + end + + def test_options_before_application_name_raises_an_error + content = capture(:stderr){ run_generator(["--pretend", destination_root]) } + assert_match /Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content + end + + def test_name_collision_raises_an_error + reserved_words = %w[application destroy plugin runner test] + reserved_words.each do |reserved| + content = capture(:stderr){ run_generator [File.join(destination_root, reserved)] } + assert_match /Invalid \w+ name #{reserved}. Please give a name which does not match one of the reserved rails words.\n/, content + end + end + + def test_name_raises_an_error_if_name_already_used_constant + %w{ String Hash Class Module Set Symbol }.each do |ruby_class| + content = capture(:stderr){ run_generator [File.join(destination_root, ruby_class)] } + assert_match /Invalid \w+ name #{ruby_class}, constant #{ruby_class} is already in use. Please choose another \w+ name.\n/, content + end + end + + def test_shebang_is_added_to_rails_file + run_generator [destination_root, "--ruby", "foo/bar/baz"] + assert_file "script/rails", /#!foo\/bar\/baz/ + end + + def test_shebang_when_is_the_same_as_default_use_env + run_generator [destination_root, "--ruby", Thor::Util.ruby_command] + assert_file "script/rails", /#!\/usr\/bin\/env/ + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } + assert_match /The template \[.*\] could not be loaded/, content + assert_match /non\/existant\/path/, content + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + template = %{ say "It works!" } + template.instance_eval "def read; self; end" # Make the string respond to read + + generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + assert_match /It works!/, silence(:stdout){ generator.invoke_all } + end + + def test_dev_option + generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + rails_path = File.expand_path('../../..', Rails.root) + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ + end + + def test_edge_option + generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} + end + + def test_template_raises_an_error_with_invalid_path + content = capture(:stderr){ run_generator([destination_root, "-m", "non/existant/path"]) } + assert_match /The template \[.*\] could not be loaded/, content + assert_match /non\/existant\/path/, content + end + + def test_template_is_executed_when_supplied + path = "http://gist.github.com/103208.txt" + template = %{ say "It works!" } + template.instance_eval "def read; self; end" # Make the string respond to read + + generator([destination_root], :template => path).expects(:open).with(path, 'Accept' => 'application/x-thor-template').returns(template) + assert_match /It works!/, silence(:stdout){ generator.invoke_all } + end + + def test_dev_option + generator([destination_root], :dev => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + rails_path = File.expand_path('../../..', Rails.root) + assert_file 'Gemfile', /^gem\s+["']rails["'],\s+:path\s+=>\s+["']#{Regexp.escape(rails_path)}["']$/ + end + + def test_edge_option + generator([destination_root], :edge => true).expects(:run).with("#{@bundle_command} install") + silence(:stdout){ generator.invoke_all } + assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+:git\s+=>\s+["']#{Regexp.escape("git://github.com/rails/rails.git")}["']$} + end +end + +module SharedCustomGeneratorTests + 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 do + remove_const :AppBuilder if const_defined?(:AppBuilder) + remove_const :PluginBuilder if const_defined?(:PluginBuilder) + end + Rails.application = TestApp::Application.instance + end + + def test_builder_option_with_empty_app_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/empty_builder.rb"]) + default_files.each{ |path| assert_no_file path } + end + + def test_builder_option_with_simple_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/simple_builder.rb"]) + (default_files - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + 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/#{builders_dir}/simple_builder.rb"]) + FileUtils.cd(destination_root) + (default_files - ['.gitignore']).each{ |path| assert_no_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_tweak_plugin_builder + FileUtils.cd(destination_root) + run_generator([destination_root, "-b", "#{Rails.root}/lib/#{builders_dir}/tweak_builder.rb"]) + default_files.each{ |path| assert_file path } + assert_file ".gitignore", "foobar" + end + + def test_builder_option_with_http + path = "http://gist.github.com/103208.txt" + template = "class #{builder_class}; 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_files.each{ |path| assert_no_file path } + end +end From 48fef64cb5d38b2ac81a483bb0fad89c2134dcdc Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 21 Oct 2010 15:23:07 +0200 Subject: [PATCH 12/36] Builder should not be responsible for running store_application_definition method --- .../rails/generators/rails/plugin_new/plugin_new_generator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 8296f37211..2fdd67944e 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -41,7 +41,6 @@ module Rails end def test_dummy_config - store_application_definition! template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true end @@ -168,6 +167,7 @@ end say_step "Configuring Rails application" def change_config_files + store_application_definition! build(:test_dummy_config) end From ac8f9276f5a5e8dea5d68c20daf5f5a69a299b88 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 21 Oct 2010 15:25:41 +0200 Subject: [PATCH 13/36] We don't need gem tasks, we have a gemspec --- .../rails/plugin_new/templates/Rakefile | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile index af5f672396..3c53b677a0 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -8,7 +8,6 @@ end require 'rake' require 'rake/rdoctask' -require 'rake/gempackagetask' <%= rakefile_test_tasks %> @@ -21,19 +20,3 @@ Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_files.include('README.rdoc') rdoc.rdoc_files.include('lib/**/*.rb') end - -spec = Gem::Specification.new do |s| - s.name = "<%= name %>" - s.summary = "Insert <%= camelized %> summary." - s.description = "Insert <%= camelized %> description." - s.files = FileList["[A-Z]*", "lib/**/*"] - s.version = "0.0.1" -end - -Rake::GemPackageTask.new(spec) do |pkg| -end - -desc "Install the gem #{spec.name}-#{spec.version}.gem" -task :install do - system("gem install pkg/#{spec.name}-#{spec.version}.gem --no-ri --no-rdoc") -end From 68295bc69349fc4fd4f8fa2023cf369b70039848 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 23 Oct 2010 18:24:04 +0200 Subject: [PATCH 14/36] Remove integration tests and ActionModel/ActiveRecord calls from 'rake plugin new' generator, it shouldn't be available as default option --- .../rails/plugin_new/plugin_new_generator.rb | 5 +++-- .../generators/rails/plugin_new/templates/Gemfile | 3 --- .../plugin_new/templates/rails/application.rb | 6 +----- .../test/integration/navigation_test.rb.tt | 7 ------- .../templates/test/support/integration_case.rb | 5 ----- .../rails/plugin_new/templates/test/test_helper.rb | 14 +------------- railties/test/generators/app_generator_test.rb | 2 +- .../test/generators/plugin_new_generator_test.rb | 8 +------- 8 files changed, 7 insertions(+), 43 deletions(-) delete mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt delete mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 2fdd67944e..67b9c968d7 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -215,8 +215,9 @@ end def application_definition @application_definition ||= begin - unless options[:pretend] - contents = File.read(File.expand_path("#{dummy_path}/config/application.rb", destination_root)) + dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root) + unless options[:pretend] || !File.exists?(dummy_application_path) + contents = File.read(dummy_application_path) contents[(contents.index("module Dummy"))..-1] end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 899a9366d3..53a925d976 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -2,9 +2,6 @@ source "http://rubygems.org" <%= rails_gemfile_entry -%> -gem "capybara", ">= 0.3.9" -gem "sqlite3-ruby", :require => "sqlite3" - if RUBY_VERSION < '1.9' gem "ruby-debug", ">= 0.10.3" end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb index fee63ea83e..ce655ba7e5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb @@ -1,10 +1,6 @@ require File.expand_path('../boot', __FILE__) -require "active_model/railtie" -require "active_record/railtie" -require "action_controller/railtie" -require "action_view/railtie" -require "action_mailer/railtie" +require 'rails/all' Bundler.require require "<%= name %>" diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt deleted file mode 100644 index 42721899c8..0000000000 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb.tt +++ /dev/null @@ -1,7 +0,0 @@ -require 'test_helper' - -class NagivationTest < ActiveSupport::IntegrationCase - test "truth" do - assert_kind_of Dummy::Application, Rails.application - end -end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb deleted file mode 100644 index 4cfe3f0e71..0000000000 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Define a bare test case to use with Capybara -class ActiveSupport::IntegrationCase < ActiveSupport::TestCase - include Capybara - include Rails.application.routes.url_helpers -end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index 5c39780a23..791b901593 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -4,19 +4,7 @@ ENV["RAILS_ENV"] = "test" require File.expand_path("../dummy/config/environment.rb", __FILE__) require "rails/test_help" -ActionMailer::Base.delivery_method = :test -ActionMailer::Base.perform_deliveries = true -ActionMailer::Base.default_url_options[:host] = "test.com" - Rails.backtrace_cleaner.remove_silencers! -# Configure capybara for integration testing -require "capybara/rails" -Capybara.default_driver = :rack_test -Capybara.default_selector = :css - -# Run any available migration -ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) - # Load support files -Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } \ No newline at end of file +Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 1f0ef922cd..42a49eb03c 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -145,7 +145,7 @@ class AppGeneratorTest < Rails::Generators::TestCase def test_test_unit_is_skipped_if_required run_generator [destination_root, "--skip-test-unit"] - assert_no_file "test" + assert_no_file "test" end def test_javascript_is_skipped_if_required diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index e8a9c8ff51..2049d31b18 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -13,8 +13,6 @@ DEFAULT_PLUGIN_FILES = %w( lib/bukkits.rb script/rails test/bukkits_test.rb - test/integration/navigation_test.rb - test/support/integration_case.rb test/test_helper.rb test/dummy ) @@ -43,12 +41,8 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_generating_test_files run_generator assert_file "test/test_helper.rb" - assert_directory "test/support/" - assert_directory "test/integration/" assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ - assert_file "test/integration/navigation_test.rb", /assert_kind_of Dummy::Application, Rails.application/ - assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/ end def test_ensure_that_plugin_options_are_not_passed_app_generator @@ -66,7 +60,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase run_generator FileUtils.cd destination_root `bundle install` - assert_match /2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test` + assert_match /1 tests, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test` end protected From d995953869ca09906af8f5c5058d47cb66bc2467 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 23 Oct 2010 20:42:01 +0200 Subject: [PATCH 15/36] DRY up app generator and plugin new generator. Moved shared options to AppBase generator --- railties/lib/rails/generators/app_base.rb | 28 ++++++++++++++++++ .../generators/rails/app/app_generator.rb | 26 +---------------- .../rails/plugin_new/plugin_new_generator.rb | 29 ++----------------- 3 files changed, 31 insertions(+), 52 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index e0f0242da8..ad44d9a14e 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -8,6 +8,34 @@ require 'uri' module Rails module Generators class AppBase < Base + attr_accessor :rails_template + add_shebang_option! + + argument :app_path, :type => :string + + def self.add_shared_options_for(name) + class_option :builder, :type => :string, :aliases => "-b", + :desc => "Path to a #{name} builder (can be a filesystem path or URL)" + + class_option :template, :type => :string, :aliases => "-m", + :desc => "Path to an #{name} template (can be a filesystem path or URL)" + + class_option :skip_gemfile, :type => :boolean, :default => false, + :desc => "Don't create a Gemfile" + + class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, + :desc => "Skip Git ignores and keeps" + + class_option :dev, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" + + class_option :edge, :type => :boolean, :default => false, + :desc => "Setup the #{name} with Gemfile pointing to Rails repository" + + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, + :desc => "Show this help message and quit" + end + def self.say_step(message) @step = (@step || 0) + 1 class_eval <<-METHOD, __FILE__, __LINE__ + 1 diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 7c89eabedd..04c2e3738a 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -157,10 +157,7 @@ module Rails DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) JAVASCRIPTS = %w( prototype jquery ) - attr_accessor :rails_template - add_shebang_option! - - argument :app_path, :type => :string + add_shared_options_for "application" class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" @@ -168,21 +165,6 @@ module Rails class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype", :desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.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)" - - class_option :dev, :type => :boolean, :default => false, - :desc => "Setup the application with Gemfile pointing to your Rails checkout" - - class_option :edge, :type => :boolean, :default => false, - :desc => "Setup the application with Gemfile pointing to Rails repository" - - class_option :skip_gemfile, :type => :boolean, :default => false, - :desc => "Don't create a Gemfile" - class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, :desc => "Skip Active Record files" @@ -192,16 +174,10 @@ module Rails class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, :desc => "Skip javascript files" - class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, - :desc => "Skip Git ignores and keeps" - # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" - class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, - :desc => "Show this help message and quit" - def initialize(*args) raise Error, "Options should be given after the application name. For details run: rails --help" if args[0].blank? diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 67b9c968d7..9c0d83cd70 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -92,34 +92,9 @@ end module Generators class PluginNewGenerator < AppBase - attr_accessor :rails_template - - add_shebang_option! - - argument :plugin_path, :type => :string - alias_method :app_path, :plugin_path - - class_option :builder, :type => :string, :aliases => "-b", - :desc => "Path to a plugin 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)" - - class_option :skip_gemfile, :type => :boolean, :default => false, - :desc => "Don't create a Gemfile" - - class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, - :desc => "Skip Git ignores and keeps" - - class_option :dev, :type => :boolean, :default => false, - :desc => "Setup the plugin with Gemfile pointing to your Rails checkout" - - class_option :edge, :type => :boolean, :default => false, - :desc => "Setup the plugin with Gemfile pointing to Rails repository" - - class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, - :desc => "Show this help message and quit" + add_shared_options_for "plugin" + alias_method :plugin_path, :app_path def initialize(*args) raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? From fdbd9df21e0063da4b34346c54fbe21ac9583ca6 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 23 Oct 2010 20:56:02 +0200 Subject: [PATCH 16/36] No need for say_step in 'plugin new' generator --- railties/lib/rails/generators/app_base.rb | 10 ---------- .../rails/plugin_new/plugin_new_generator.rb | 9 +-------- railties/test/generators/plugin_new_generator_test.rb | 7 +++---- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index ad44d9a14e..a355f3b055 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -36,16 +36,6 @@ module Rails :desc => "Show this help message and quit" end - def self.say_step(message) - @step = (@step || 0) + 1 - class_eval <<-METHOD, __FILE__, __LINE__ + 1 - def step_#{@step} - #{"puts" if @step > 1} - say_status "STEP #{@step}", #{message.inspect} - end - METHOD - end - def initialize(*args) @original_wd = Dir.pwd diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 9c0d83cd70..8c4ddc822a 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -102,8 +102,6 @@ end super end - say_step "Creating gem skeleton" - def create_root super end @@ -133,21 +131,16 @@ end build(:test) unless options[:skip_test_unit] end - say_step "Vendoring Rails application at test/dummy" - def create_test_dummy_files + say_status :vendor_app, dummy_path build(:generate_test_dummy) end - say_step "Configuring Rails application" - def change_config_files store_application_definition! build(:test_dummy_config) end - say_step "Removing unneeded files" - def remove_uneeded_rails_files build(:test_dummy_clean) end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 2049d31b18..bf395749e5 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -45,10 +45,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ end - def test_ensure_that_plugin_options_are_not_passed_app_generator - output = run_generator [destination_root, "--skip_gemfile"] - assert_no_file "Gemfile" - assert_match /STEP 2.*create Gemfile/m, output + def test_ensure_that_plugin_options_are_not_passed_to_app_generator + FileUtils.cd(Rails.root) + assert_no_match /It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"]) end def test_template_from_dir_pwd From 671d1469c6f70abb7cbd373bb37f18268ed7069c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 26 Oct 2010 22:22:15 +0200 Subject: [PATCH 17/36] Add --full option to 'plugin new' generator, which generates rails engine --- Gemfile | 3 ++ railties/lib/rails/generators/app_base.rb | 5 ++++ .../generators/rails/app/app_generator.rb | 3 -- .../rails/plugin_new/plugin_new_generator.rb | 25 +++++++++++++++-- .../rails/plugin_new/templates/Gemfile | 5 ++++ .../rails/plugin_new/templates/lib/%name%.rb | 6 ++++ .../plugin_new/templates/lib/%name%.rb.tt | 2 -- .../plugin_new/templates/lib/%name%/engine.rb | 4 +++ .../plugin_new/templates/rails/application.rb | 8 ++++++ .../{%name%_test.rb.tt => %name%_test.rb} | 0 .../test/integration/navigation_test.rb | 7 +++++ .../test/support/integration_case.rb | 5 ++++ .../plugin_new/templates/test/test_helper.rb | 16 +++++++++++ .../generators/plugin_new_generator_test.rb | 28 ++++++++++++++++++- 14 files changed, 108 insertions(+), 9 deletions(-) create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb delete mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb rename railties/lib/rails/generators/rails/plugin_new/templates/test/{%name%_test.rb.tt => %name%_test.rb} (100%) create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb diff --git a/Gemfile b/Gemfile index 66a446a177..202a84ced4 100644 --- a/Gemfile +++ b/Gemfile @@ -25,6 +25,9 @@ gem "memcache-client", ">= 1.8.5" # AM gem "text-format", "~> 1.0.0" +# for 'plugin new --full' generator +gem "capybara" + platforms :mri_18 do gem "system_timer" gem "ruby-debug", ">= 0.10.3" diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index a355f3b055..1b3673e96e 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -26,6 +26,11 @@ module Rails class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, :desc => "Skip Git ignores and keeps" + skip_active_record_desc = "Skip Active Record files" + skip_active_record_desc << " for dummy application" if name == "plugin" + class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, + :desc => skip_active_record_desc + class_option :dev, :type => :boolean, :default => false, :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 04c2e3738a..6fdc51bd94 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -165,9 +165,6 @@ module Rails class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype", :desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})" - class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, - :desc => "Skip Active Record files" - class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, :desc => "Skip Test::Unit files" diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 8c4ddc822a..d361c490a3 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/hash/slice' require 'rails/generators/app_base' require "rails/generators/rails/app/app_generator" @@ -28,16 +29,26 @@ module Rails end def lib - directory "lib" + template "lib/%name%.rb" + if full? + template "lib/%name%/engine.rb" + end end def test - directory "test" + template "test/test_helper.rb" + template "test/%name%_test.rb" + if full? + template "test/integration/navigation_test.rb" + template "test/support/integration_case.rb" + end end def generate_test_dummy + opts = (options || {}).slice("skip_active_record") + invoke Rails::Generators::AppGenerator, - [ File.expand_path(dummy_path, destination_root) ], {} + [ File.expand_path(dummy_path, destination_root) ], opts end def test_dummy_config @@ -96,6 +107,9 @@ end alias_method :plugin_path, :app_path + class_option :full, :type => :boolean, :default => false, + :desc => "Generate rails engine with integration tests" + def initialize(*args) raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? @@ -159,6 +173,10 @@ end protected + def full? + options[:full] + end + def self.banner "rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]" end @@ -183,6 +201,7 @@ end def application_definition @application_definition ||= begin + dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root) unless options[:pretend] || !File.exists?(dummy_application_path) contents = File.read(dummy_application_path) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 53a925d976..7ce44a3d52 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -2,6 +2,11 @@ source "http://rubygems.org" <%= rails_gemfile_entry -%> +<% if full? -%> + gem "capybara", ">= 0.3.9" + gem "sqlite3-ruby", :require => "sqlite3" +<% end -%> + if RUBY_VERSION < '1.9' gem "ruby-debug", ">= 0.10.3" end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb new file mode 100644 index 0000000000..805ba008c3 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb @@ -0,0 +1,6 @@ +<% if full? %> +require "<%= name %>/engine" + +<% end -%> +module <%= camelized %> +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt deleted file mode 100644 index cf77a0b4d3..0000000000 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb.tt +++ /dev/null @@ -1,2 +0,0 @@ -module <%= camelized %> -end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb new file mode 100644 index 0000000000..779bd1cfd3 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb @@ -0,0 +1,4 @@ +module <%= camelized %> + class Engine < Rails::Engine + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb index ce655ba7e5..8b68280a5e 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/application.rb @@ -1,6 +1,14 @@ require File.expand_path('../boot', __FILE__) +<% unless options[:skip_active_record] -%> require 'rails/all' +<% else -%> +# require "active_record/railtie" +require "action_controller/railtie" +require "action_mailer/railtie" +require "active_resource/railtie" +require "rails/test_unit/railtie" +<% end -%> Bundler.require require "<%= name %>" diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb similarity index 100% rename from railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb.tt rename to railties/lib/rails/generators/rails/plugin_new/templates/test/%name%_test.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb new file mode 100644 index 0000000000..42721899c8 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class NagivationTest < ActiveSupport::IntegrationCase + test "truth" do + assert_kind_of Dummy::Application, Rails.application + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb new file mode 100644 index 0000000000..4cfe3f0e71 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb @@ -0,0 +1,5 @@ +# Define a bare test case to use with Capybara +class ActiveSupport::IntegrationCase < ActiveSupport::TestCase + include Capybara + include Rails.application.routes.url_helpers +end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index 791b901593..d821079b91 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -6,5 +6,21 @@ require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! +<% if full? -%> +ActionMailer::Base.delivery_method = :test +ActionMailer::Base.perform_deliveries = true +ActionMailer::Base.default_url_options[:host] = "test.com" + +# Configure capybara for integration testing +require "capybara/rails" +Capybara.default_driver = :rack_test +Capybara.default_selector = :css + +# Run any available migration from application +ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) +# and from engine +ActiveRecord::Migrator.migrate File.expand_path("../../db/migrate/", __FILE__) +<% end -%> + # Load support files Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index bf395749e5..f833411e3a 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -41,15 +41,28 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_generating_test_files run_generator assert_file "test/test_helper.rb" - assert_file "test/bukkits_test.rb", /assert_kind_of Module, Bukkits/ end + def test_generating_test_files_in_full_mode + run_generator [destination_root, "--full"] + assert_directory "test/support/" + assert_directory "test/integration/" + + assert_file "test/integration/navigation_test.rb", /assert_kind_of Dummy::Application, Rails.application/ + assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/ + end + def test_ensure_that_plugin_options_are_not_passed_to_app_generator FileUtils.cd(Rails.root) assert_no_match /It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"]) end + def test_ensure_that_skip_active_record_option_is_passed_to_app_generator + run_generator [destination_root, "--skip_active_record"] + assert_no_file "test/dummy/config/database.yml" + end + def test_template_from_dir_pwd FileUtils.cd(Rails.root) assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) @@ -62,6 +75,19 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_match /1 tests, 1 assertions, 0 failures, 0 errors/, `bundle exec rake test` end + def test_ensure_that_tests_works_in_full_mode + run_generator [destination_root, "--full"] + FileUtils.cd destination_root + `bundle install` + assert_match /2 tests, 2 assertions, 0 failures, 0 errors/, `bundle exec rake test` + end + + def test_creating_engine_in_full_mode + run_generator [destination_root, "--full"] + assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < Rails::Engine\n end\nend/ + assert_file "lib/bukkits.rb", /require "bukkits\/engine"/ + end + protected def action(*args, &block) From 46fdb3197d270551da260cfed3dea7928dd15b0f Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 27 Oct 2010 00:16:57 +0200 Subject: [PATCH 18/36] Pass more options to test/dummy in 'plugin new' generator --- railties/lib/rails/generators/app_base.rb | 16 +++++++++++++--- .../rails/generators/rails/app/app_generator.rb | 12 ------------ .../rails/plugin_new/plugin_new_generator.rb | 2 +- .../test/generators/plugin_new_generator_test.rb | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 1b3673e96e..0bf5ee86b1 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -8,6 +8,9 @@ require 'uri' module Rails module Generators class AppBase < Base + DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + JAVASCRIPTS = %w( prototype jquery ) + attr_accessor :rails_template add_shebang_option! @@ -26,10 +29,17 @@ module Rails class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false, :desc => "Skip Git ignores and keeps" - skip_active_record_desc = "Skip Active Record files" - skip_active_record_desc << " for dummy application" if name == "plugin" class_option :skip_active_record, :type => :boolean, :aliases => "-O", :default => false, - :desc => skip_active_record_desc + :desc => "Skip Active Record files" + + class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", + :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" + + class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype", + :desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})" + + class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, + :desc => "Skip javascript files" class_option :dev, :type => :boolean, :default => false, :desc => "Setup the #{name} with Gemfile pointing to your Rails checkout" diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 6fdc51bd94..ef24cf1e05 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -154,23 +154,11 @@ module Rails plugin runner test] class AppGenerator < AppBase - DATABASES = %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) - JAVASCRIPTS = %w( prototype jquery ) - add_shared_options_for "application" - class_option :database, :type => :string, :aliases => "-d", :default => "sqlite3", - :desc => "Preconfigure for selected database (options: #{DATABASES.join('/')})" - - class_option :javascript, :type => :string, :aliases => "-j", :default => "prototype", - :desc => "Preconfigure for selected javascript library (options: #{JAVASCRIPTS.join('/')})" - class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, :desc => "Skip Test::Unit files" - class_option :skip_javascript, :type => :boolean, :aliases => "-J", :default => false, - :desc => "Skip javascript files" - # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index d361c490a3..b514554da7 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -45,7 +45,7 @@ module Rails end def generate_test_dummy - opts = (options || {}).slice("skip_active_record") + opts = (options || {}).slice(:skip_active_record, :skip_javascript, :database, :javascript) invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], opts diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index f833411e3a..53e1dd6708 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -63,6 +63,21 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_no_file "test/dummy/config/database.yml" end + def test_ensure_that_database_option_is_passed_to_app_generator + run_generator [destination_root, "--database", "postgresql"] + assert_file "test/dummy/config/database.yml", /postgres/ + end + + def test_ensure_that_javascript_option_is_passed_to_app_generator + run_generator [destination_root, "--javascript", "jquery"] + assert_file "test/dummy/public/javascripts/jquery.js" + end + + def test_ensure_that_skip_javascript_option_is_passed_to_app_generator + run_generator [destination_root, "--skip_javascript"] + assert_no_file "test/dummy/public/javascripts/prototype.js" + end + def test_template_from_dir_pwd FileUtils.cd(Rails.root) assert_match /It works from file!/, run_generator([destination_root, "-m", "lib/template.rb"]) From 013fc0a418379d6f62bbd1f86d2b5bd674927fe7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 27 Oct 2010 00:31:29 +0200 Subject: [PATCH 19/36] No need to require 'app_base', it's required in app_generator --- .../rails/generators/rails/plugin_new/plugin_new_generator.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index b514554da7..e464279af6 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/hash/slice' -require 'rails/generators/app_base' require "rails/generators/rails/app/app_generator" module Rails From 489b279fc499f135df48556554739c19d316df0a Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 28 Oct 2010 03:00:42 +0200 Subject: [PATCH 20/36] Don't be verbose while creating dummy application in plugin new generator --- Gemfile | 2 ++ .../rails/plugin_new/plugin_new_generator.rb | 16 +++++++++++++--- .../test/generators/plugin_new_generator_test.rb | 4 ++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 202a84ced4..a23d482703 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,8 @@ else gem "arel", :git => "git://github.com/rails/arel.git" end +gem "thor", :git => "git://github.com/wycats/thor.git" + gem "rack", :git => "git://github.com/rack/rack.git" gem "rails", :path => File.dirname(__FILE__) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index e464279af6..7b202344ee 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -146,16 +146,22 @@ end def create_test_dummy_files say_status :vendor_app, dummy_path - build(:generate_test_dummy) + mute do + build(:generate_test_dummy) + end end def change_config_files store_application_definition! - build(:test_dummy_config) + mute do + build(:test_dummy_config) + end end def remove_uneeded_rails_files - build(:test_dummy_clean) + mute do + build(:test_dummy_clean) + end end def finish_template @@ -219,6 +225,10 @@ end builder.send(name) if builder.respond_to?(name) end end + + def mute(&block) + shell.mute(&block) + end end end end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 53e1dd6708..985ef088e5 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -103,6 +103,10 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "lib/bukkits.rb", /require "bukkits\/engine"/ end + def test_being_quiet_while_creating_dummy_application + assert_no_match /create\s+config\/application.rb/, run_generator + end + protected def action(*args, &block) From 9e86767bb88f45db0f9aef42b1bea1177cba8e53 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 28 Oct 2010 17:22:41 +0200 Subject: [PATCH 21/36] Do not create additional newline --- .../rails/generators/rails/plugin_new/templates/lib/%name%.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb index 805ba008c3..2d3bdc510c 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb @@ -1,4 +1,4 @@ -<% if full? %> +<% if full? -%> require "<%= name %>/engine" <% end -%> From cfbe5958311f21397c98657c3370d03dcf720fe1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 28 Oct 2010 18:00:52 +0200 Subject: [PATCH 22/36] Use application's generators defaults as engine defaults to not force users to manually set it --- activerecord/lib/active_record/railtie.rb | 2 +- railties/lib/rails/engine/configuration.rb | 1 + railties/test/railties/engine_test.rb | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 868fd6c3ff..dfe255ad7c 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -14,7 +14,7 @@ module ActiveRecord config.active_record = ActiveSupport::OrderedOptions.new config.app_generators.orm :active_record, :migration => true, - :timestamps => true + :timestamps => true config.app_middleware.insert_after "::ActionDispatch::Callbacks", "ActiveRecord::QueryCache" diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 7a07dcad7d..5607628d96 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -10,6 +10,7 @@ module Rails def initialize(root=nil) super() @root = root + @generators = app_generators end # Returns the middleware stack for the engine. diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 4b52260ecc..3509f964eb 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -685,5 +685,22 @@ module RailtiesTest assert_equal :haml , generators[:template_engine] assert_equal :rspec , generators[:test_framework] end + + test "engine should get default generators with ability to overwrite them" do + @plugin.write "lib/bukkits.rb", <<-RUBY + module Bukkits + class Engine < ::Rails::Engine + config.generators.test_framework :rspec + end + end + RUBY + + boot_rails + require "#{rails_root}/config/environment" + + generators = Bukkits::Engine.config.generators.options[:rails] + assert_equal :active_record, generators[:orm] + assert_equal :rspec , generators[:test_framework] + end end end From 5071b727b438f1ca6be502c906f5af751abb0229 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 28 Oct 2010 19:43:21 +0200 Subject: [PATCH 23/36] Added Hash#deep_dup function which performs deep duplication on given hash --- activesupport/lib/active_support/core_ext/hash.rb | 1 + .../lib/active_support/core_ext/hash/deep_dup.rb | 11 +++++++++++ activesupport/test/core_ext/hash_ext_test.rb | 15 +++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 activesupport/lib/active_support/core_ext/hash/deep_dup.rb diff --git a/activesupport/lib/active_support/core_ext/hash.rb b/activesupport/lib/active_support/core_ext/hash.rb index 501483498d..fd1cda991e 100644 --- a/activesupport/lib/active_support/core_ext/hash.rb +++ b/activesupport/lib/active_support/core_ext/hash.rb @@ -1,5 +1,6 @@ require 'active_support/core_ext/hash/conversions' require 'active_support/core_ext/hash/deep_merge' +require 'active_support/core_ext/hash/deep_dup' require 'active_support/core_ext/hash/diff' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/hash/indifferent_access' diff --git a/activesupport/lib/active_support/core_ext/hash/deep_dup.rb b/activesupport/lib/active_support/core_ext/hash/deep_dup.rb new file mode 100644 index 0000000000..447142605c --- /dev/null +++ b/activesupport/lib/active_support/core_ext/hash/deep_dup.rb @@ -0,0 +1,11 @@ +class Hash + # Returns a deep copy of hash. + def deep_dup + duplicate = self.dup + duplicate.each_pair do |k,v| + tv = duplicate[k] + duplicate[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_dup : v + end + duplicate + end +end diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb index 545fed2684..bfcfddad47 100644 --- a/activesupport/test/core_ext/hash_ext_test.rb +++ b/activesupport/test/core_ext/hash_ext_test.rb @@ -316,6 +316,21 @@ class HashExtTest < Test::Unit::TestCase assert_equal expected, hash_1 end + def test_deep_dup + hash = { :a => { :b => 'b' } } + dup = hash.deep_dup + dup[:a][:c] = 'c' + assert_equal nil, hash[:a][:c] + assert_equal 'c', dup[:a][:c] + end + + def test_deep_dup_initialize + zero_hash = Hash.new 0 + hash = { :a => zero_hash } + dup = hash.deep_dup + assert_equal 0, dup[:a][44] + end + def test_store_on_indifferent_access hash = HashWithIndifferentAccess.new hash.store(:test1, 1) From a5311ee86bffad3f0bce00babd1ff5d78ec85618 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 28 Oct 2010 20:25:20 +0200 Subject: [PATCH 24/36] Make deep copy of application generators on engine initialization. Otherwise nested hashes will be same objects for both application and engine, which will result in overwriting each others values on changes. --- railties/lib/rails/configuration.rb | 8 ++++++++ railties/lib/rails/engine/configuration.rb | 2 +- railties/test/railties/engine_test.rb | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb index 8369795e71..66fab0a760 100644 --- a/railties/lib/rails/configuration.rb +++ b/railties/lib/rails/configuration.rb @@ -1,5 +1,6 @@ require 'active_support/deprecation' require 'active_support/ordered_options' +require 'active_support/core_ext/hash/deep_dup' require 'rails/paths' require 'rails/rack' @@ -51,6 +52,13 @@ module Rails @colorize_logging = true end + def initialize_copy(source) + @aliases = @aliases.deep_dup + @options = @options.deep_dup + @fallbacks = @fallbacks.deep_dup + @templates = @templates.dup + end + def method_missing(method, *args) method = method.to_s.sub(/=$/, '').to_sym diff --git a/railties/lib/rails/engine/configuration.rb b/railties/lib/rails/engine/configuration.rb index 5607628d96..4f458b0aee 100644 --- a/railties/lib/rails/engine/configuration.rb +++ b/railties/lib/rails/engine/configuration.rb @@ -10,7 +10,7 @@ module Rails def initialize(root=nil) super() @root = root - @generators = app_generators + @generators = app_generators.dup end # Returns the middleware stack for the engine. diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 3509f964eb..822be24ef1 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -701,6 +701,9 @@ module RailtiesTest generators = Bukkits::Engine.config.generators.options[:rails] assert_equal :active_record, generators[:orm] assert_equal :rspec , generators[:test_framework] + + app_generators = Rails.application.config.generators.options[:rails] + assert_equal :test_unit , app_generators[:test_framework] end end end From 9cb9713eebd786bd5113470af67b6c81bb57986e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 29 Oct 2010 20:06:48 +0200 Subject: [PATCH 25/36] Refactor app and plugin generators to use new Thor API --- .../lib/rails/generators/rails/app/app_generator.rb | 12 ++---------- .../rails/plugin_new/plugin_new_generator.rb | 12 ++---------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index ef24cf1e05..e2d2ae71ba 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -177,9 +177,7 @@ module Rails end end - def create_root - super - end + public_task :create_root def create_root_files build(:readme) @@ -258,13 +256,7 @@ module Rails build(:leftovers) end - def apply_rails_template - super - end - - def bundle_if_dev_or_edge - super - end + public_task :apply_rails_template, :bundle_if_dev_or_edge protected diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 7b202344ee..ddc801a0ae 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -115,9 +115,7 @@ end super end - def create_root - super - end + public_task :create_root def create_root_files build(:readme) @@ -168,13 +166,7 @@ end build(:leftovers) end - def apply_rails_template - super - end - - def bundle_if_dev_or_edge - super - end + public_task :apply_rails_template, :bundle_if_dev_or_edge protected From 4d108cb33d818949e7682076ad662c99168093e4 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 12:56:00 +0100 Subject: [PATCH 26/36] We don't need to configure ActionMailer in plugin's test helper, it's configured by dummy app --- .../generators/rails/plugin_new/templates/test/test_helper.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index d821079b91..4562c88a54 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -7,10 +7,6 @@ require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! <% if full? -%> -ActionMailer::Base.delivery_method = :test -ActionMailer::Base.perform_deliveries = true -ActionMailer::Base.default_url_options[:host] = "test.com" - # Configure capybara for integration testing require "capybara/rails" Capybara.default_driver = :rack_test From 57fae9b2c7d193ec16baf38a8797588fb466db49 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 14:05:11 +0100 Subject: [PATCH 27/36] Use rails integration tests by default in 'plugin new' generator --- Gemfile | 3 --- .../rails/plugin_new/plugin_new_generator.rb | 1 - .../generators/rails/plugin_new/templates/Gemfile | 1 - .../templates/test/integration/navigation_test.rb | 10 +++++++--- .../templates/test/support/integration_case.rb | 5 ----- .../rails/plugin_new/templates/test/test_helper.rb | 5 ----- railties/test/generators/plugin_new_generator_test.rb | 4 +--- 7 files changed, 8 insertions(+), 21 deletions(-) delete mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb diff --git a/Gemfile b/Gemfile index a23d482703..ac9c63790c 100644 --- a/Gemfile +++ b/Gemfile @@ -27,9 +27,6 @@ gem "memcache-client", ">= 1.8.5" # AM gem "text-format", "~> 1.0.0" -# for 'plugin new --full' generator -gem "capybara" - platforms :mri_18 do gem "system_timer" gem "ruby-debug", ">= 0.10.3" diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index ddc801a0ae..ef3ded424d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -39,7 +39,6 @@ module Rails template "test/%name%_test.rb" if full? template "test/integration/navigation_test.rb" - template "test/support/integration_case.rb" end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 7ce44a3d52..928ea8b9c4 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -3,7 +3,6 @@ source "http://rubygems.org" <%= rails_gemfile_entry -%> <% if full? -%> - gem "capybara", ">= 0.3.9" gem "sqlite3-ruby", :require => "sqlite3" <% end -%> diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb index 42721899c8..d06fe7cbd0 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/integration/navigation_test.rb @@ -1,7 +1,11 @@ require 'test_helper' -class NagivationTest < ActiveSupport::IntegrationCase - test "truth" do - assert_kind_of Dummy::Application, Rails.application +class NavigationTest < ActionDispatch::IntegrationTest + fixtures :all + + # Replace this with your real tests. + test "the truth" do + assert true end end + diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb deleted file mode 100644 index 4cfe3f0e71..0000000000 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/support/integration_case.rb +++ /dev/null @@ -1,5 +0,0 @@ -# Define a bare test case to use with Capybara -class ActiveSupport::IntegrationCase < ActiveSupport::TestCase - include Capybara - include Rails.application.routes.url_helpers -end \ No newline at end of file diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index 4562c88a54..b42e45d544 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -7,11 +7,6 @@ require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! <% if full? -%> -# Configure capybara for integration testing -require "capybara/rails" -Capybara.default_driver = :rack_test -Capybara.default_selector = :css - # Run any available migration from application ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) # and from engine diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 985ef088e5..aebd954215 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -46,11 +46,9 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_generating_test_files_in_full_mode run_generator [destination_root, "--full"] - assert_directory "test/support/" assert_directory "test/integration/" - assert_file "test/integration/navigation_test.rb", /assert_kind_of Dummy::Application, Rails.application/ - assert_file "test/support/integration_case.rb", /class ActiveSupport::IntegrationCase/ + assert_file "test/integration/navigation_test.rb", /ActionDispatch::IntegrationTest/ end def test_ensure_that_plugin_options_are_not_passed_to_app_generator From b6497d3b5a84ca5e7e15700419ddf44c096c57a2 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 14:07:58 +0100 Subject: [PATCH 28/36] Skip active record properly in 'plugin new' generator --- .../generators/rails/plugin_new/templates/test/test_helper.rb | 2 +- railties/test/generators/plugin_new_generator_test.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb index b42e45d544..dbcaf6b92f 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/test/test_helper.rb @@ -6,7 +6,7 @@ require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! -<% if full? -%> +<% if full? && !options[:skip_active_record] -%> # Run any available migration from application ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__) # and from engine diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index aebd954215..20c0d0a9bf 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -59,6 +59,7 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase def test_ensure_that_skip_active_record_option_is_passed_to_app_generator run_generator [destination_root, "--skip_active_record"] assert_no_file "test/dummy/config/database.yml" + assert_no_match /ActiveRecord/, File.read(File.join(destination_root, "test/test_helper.rb")) end def test_ensure_that_database_option_is_passed_to_app_generator From 2133495b8cdcb40a68a03aa786c4353031abe49e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 14:23:45 +0100 Subject: [PATCH 29/36] Properly handle other databases in 'plugin new' generator --- railties/lib/rails/generators/app_base.rb | 27 +++++++++++++++++++ .../generators/rails/app/app_generator.rb | 18 ------------- .../generators/rails/app/templates/Gemfile | 4 +-- .../rails/plugin_new/templates/Gemfile | 2 +- .../test/generators/app_generator_test.rb | 5 ---- .../generators/plugin_new_generator_test.rb | 17 ++++++++++++ .../test/generators/shared_generator_tests.rb | 5 ++++ 7 files changed, 51 insertions(+), 27 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 0bf5ee86b1..b7a4b16f10 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -108,6 +108,15 @@ module Rails end end + def database_gemfile_entry + entry = "" + unless options[:skip_active_record] + entry = "gem '#{gem_for_database}'" + entry << ", :require => '#{require_for_database}'" if require_for_database + end + entry + end + def rails_gemfile_entry if options.dev? <<-GEMFILE @@ -133,6 +142,24 @@ gem 'rails', '#{Rails::VERSION::STRING}' end end + def gem_for_database + # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) + case options[:database] + when "oracle" then "ruby-oci8" + when "postgresql" then "pg" + when "sqlite3" then "sqlite3-ruby" + when "frontbase" then "ruby-frontbase" + when "mysql" then "mysql2" + else options[:database] + end + end + + def require_for_database + case options[:database] + when "sqlite3" then "sqlite3" + end + end + def bundle_if_dev_or_edge bundle_command = File.basename(Thor::Util.ruby_command).sub(/ruby/, 'bundle') run "#{bundle_command} install" if dev_or_edge? diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index e2d2ae71ba..7a6a7972d2 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -306,24 +306,6 @@ module Rails ActiveSupport::SecureRandom.hex(64) end - def gem_for_database - # %w( mysql oracle postgresql sqlite3 frontbase ibm_db ) - case options[:database] - when "oracle" then "ruby-oci8" - when "postgresql" then "pg" - when "sqlite3" then "sqlite3-ruby" - when "frontbase" then "ruby-frontbase" - when "mysql" then "mysql2" - else options[:database] - end - end - - def require_for_database - case options[:database] - when "sqlite3" then "sqlite3" - end - end - def mysql_socket @mysql_socket ||= [ "/tmp/mysql.sock", # default diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index 4a37f675ad..86b9e8f40c 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -2,9 +2,7 @@ source 'http://rubygems.org' <%= rails_gemfile_entry -%> -<% unless options[:skip_active_record] -%> -gem '<%= gem_for_database %>'<% if require_for_database %>, :require => '<%= require_for_database %>'<% end %> -<% end -%> +<%= database_gemfile_entry -%> # Use unicorn as the web server # gem 'unicorn' diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile index 928ea8b9c4..29900c93dc 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile @@ -3,7 +3,7 @@ source "http://rubygems.org" <%= rails_gemfile_entry -%> <% if full? -%> - gem "sqlite3-ruby", :require => "sqlite3" +<%= database_gemfile_entry -%> <% end -%> if RUBY_VERSION < '1.9' diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index 42a49eb03c..ddd8272db6 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -53,11 +53,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_no_file "public/stylesheets/application.css" end - def test_invalid_database_option_raises_an_error - content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) } - assert_match /Invalid value for \-\-database option/, content - end - def test_invalid_application_name_raises_an_error content = capture(:stderr){ run_generator [File.join(destination_root, "43-things")] } assert_equal "Invalid application name 43-things. Please give a name which does not start with numbers.\n", content diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 20c0d0a9bf..6b7095ba78 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -56,6 +56,23 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_no_match /It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"]) end + def test_database_entry_is_assed_by_default_in_full_mode + run_generator([destination_root, "--full"]) + assert_file "test/dummy/config/database.yml", /sqlite/ + assert_file "Gemfile", /^gem\s+["']sqlite3-ruby["'],\s+:require\s+=>\s+["']sqlite3["']$/ + end + + def test_config_another_database + run_generator([destination_root, "-d", "mysql", "--full"]) + assert_file "test/dummy/config/database.yml", /mysql/ + assert_file "Gemfile", /^gem\s+["']mysql2["']$/ + end + + def test_active_record_is_removed_from_frameworks_if_skip_active_record_is_given + run_generator [destination_root, "--skip-active-record"] + assert_file "test/dummy/config/application.rb", /#\s+require\s+["']active_record\/railtie["']/ + end + def test_ensure_that_skip_active_record_option_is_passed_to_app_generator run_generator [destination_root, "--skip_active_record"] assert_no_file "test/dummy/config/database.yml" diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 71cde6785c..054a3d008a 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -30,6 +30,11 @@ module SharedGeneratorTests default_files.each{ |path| assert_no_file path } end + def test_invalid_database_option_raises_an_error + content = capture(:stderr){ run_generator([destination_root, "-d", "unknown"]) } + assert_match /Invalid value for \-\-database option/, content + end + def test_options_before_application_name_raises_an_error content = capture(:stderr){ run_generator(["--pretend", destination_root]) } assert_match /Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content From fadad11f9056a0166ee490a5eb0a4d9a01120d38 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 14:52:08 +0100 Subject: [PATCH 30/36] Properly skip test unit in 'plugin new' generator --- railties/lib/rails/generators/app_base.rb | 3 ++ .../generators/rails/app/app_generator.rb | 3 -- .../rails/plugin_new/plugin_new_generator.rb | 28 ++++++++----------- .../rails/plugin_new/templates/Rakefile | 4 ++- .../test/generators/app_generator_test.rb | 5 ---- .../test/generators/shared_generator_tests.rb | 5 ++++ 6 files changed, 22 insertions(+), 26 deletions(-) diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index b7a4b16f10..f5c626553c 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -47,6 +47,9 @@ module Rails class_option :edge, :type => :boolean, :default => false, :desc => "Setup the #{name} with Gemfile pointing to Rails repository" + class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, + :desc => "Skip Test::Unit files" + class_option :help, :type => :boolean, :aliases => "-h", :group => :rails, :desc => "Show this help message and quit" end diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb index 7a6a7972d2..ef1eb8d237 100644 --- a/railties/lib/rails/generators/rails/app/app_generator.rb +++ b/railties/lib/rails/generators/rails/app/app_generator.rb @@ -156,9 +156,6 @@ module Rails class AppGenerator < AppBase add_shared_options_for "application" - class_option :skip_test_unit, :type => :boolean, :aliases => "-T", :default => false, - :desc => "Skip Test::Unit files" - # Add bin/rails options class_option :version, :type => :boolean, :aliases => "-v", :group => :rails, :desc => "Show Rails version number and quit" diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index ef3ded424d..29a92c9388 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -142,23 +142,8 @@ end end def create_test_dummy_files - say_status :vendor_app, dummy_path - mute do - build(:generate_test_dummy) - end - end - - def change_config_files - store_application_definition! - mute do - build(:test_dummy_config) - end - end - - def remove_uneeded_rails_files - mute do - build(:test_dummy_clean) - end + return if options[:skip_test_unit] + create_test_dummy(dummy_path) end def finish_template @@ -168,6 +153,15 @@ end public_task :apply_rails_template, :bundle_if_dev_or_edge protected + def create_test_dummy(dummy_path) + say_status :vendor_app, dummy_path + mute do + build(:generate_test_dummy) + store_application_definition! + build(:test_dummy_config) + build(:test_dummy_clean) + end + end def full? options[:full] diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile index 3c53b677a0..dd7c11622d 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -9,9 +9,11 @@ end require 'rake' require 'rake/rdoctask' +<% unless options[:skip_test_unit] -%> <%= rakefile_test_tasks %> -task :default => :<%= test_path %> +task :default => :test +<% end -%> Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb index ddd8272db6..6b2026ad0c 100644 --- a/railties/test/generators/app_generator_test.rb +++ b/railties/test/generators/app_generator_test.rb @@ -138,11 +138,6 @@ class AppGeneratorTest < Rails::Generators::TestCase assert_file "test" end - def test_test_unit_is_skipped_if_required - run_generator [destination_root, "--skip-test-unit"] - assert_no_file "test" - end - def test_javascript_is_skipped_if_required run_generator [destination_root, "--skip-javascript"] assert_file "config/application.rb", /^\s+config\.action_view\.javascript_expansions\[:defaults\]\s+=\s+%w\(\)/ diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 054a3d008a..d117656fbd 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -35,6 +35,11 @@ module SharedGeneratorTests assert_match /Invalid value for \-\-database option/, content end + def test_test_unit_is_skipped_if_required + run_generator [destination_root, "--skip-test-unit"] + assert_no_file "test" + end + def test_options_before_application_name_raises_an_error content = capture(:stderr){ run_generator(["--pretend", destination_root]) } assert_match /Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content From f9e33fc09a6731ad56ff8cfe24b49532ed65039c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 15:13:10 +0100 Subject: [PATCH 31/36] create_dummy_app method that allows to easily create dummy application from template --- .../rails/plugin_new/plugin_new_generator.rb | 61 ++++++++++--------- .../rails/plugin_new/templates/Rakefile | 6 -- .../plugin_new/templates/script/rails.tt | 2 +- .../lib/create_test_dummy_template.rb | 1 + .../lib/plugin_builders/spec_builder.rb | 14 +++-- .../generators/plugin_new_generator_test.rb | 9 ++- 6 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 railties/test/fixtures/lib/create_test_dummy_template.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index 29a92c9388..eac4f76510 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -37,13 +37,19 @@ module Rails def test template "test/test_helper.rb" template "test/%name%_test.rb" + append_file "Rakefile", <<-EOF +#{rakefile_test_tasks} + +task :default => :test + EOF if full? template "test/integration/navigation_test.rb" end end - def generate_test_dummy + def generate_test_dummy(force = false) opts = (options || {}).slice(:skip_active_record, :skip_javascript, :database, :javascript) + opts[:force] = force invoke Rails::Generators::AppGenerator, [ File.expand_path(dummy_path, destination_root) ], opts @@ -70,33 +76,12 @@ module Rails end end - def script - directory "script" do |content| + def script(force = false) + directory "script", :force => force do |content| "#{shebang}\n" + content end chmod "script", 0755, :verbose => false end - - def rakefile_test_tasks - <<-RUBY -require 'rake/testtask' - -Rake::TestTask.new(:test) do |t| - t.libs << 'lib' - t.libs << 'test' - t.pattern = 'test/**/*_test.rb' - t.verbose = false -end - RUBY - end - - def dummy_path - "#{test_path}/dummy" - end - - def test_path - "test" - end end module Generators @@ -143,7 +128,7 @@ end def create_test_dummy_files return if options[:skip_test_unit] - create_test_dummy(dummy_path) + create_dummy_app end def finish_template @@ -153,13 +138,17 @@ end public_task :apply_rails_template, :bundle_if_dev_or_edge protected - def create_test_dummy(dummy_path) + def create_dummy_app(path = nil) + dummy_path(path) if path + say_status :vendor_app, dummy_path mute do build(:generate_test_dummy) store_application_definition! build(:test_dummy_config) build(:test_dummy_clean) + # ensure that script/rails has proper dummy_path + build(:script, true) end end @@ -205,10 +194,22 @@ end defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder end - [:test_path, :dummy_path, :rakefile_test_tasks].each do |name| - define_method name do - builder.send(name) if builder.respond_to?(name) - end + def rakefile_test_tasks + <<-RUBY +require 'rake/testtask' + +Rake::TestTask.new(:test) do |t| + t.libs << 'lib' + t.libs << 'test' + t.pattern = 'test/**/*_test.rb' + t.verbose = false +end + RUBY + end + + def dummy_path(path = nil) + @dummy_path = path if path + @dummy_path || "test/dummy" end def mute(&block) diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile index dd7c11622d..88f50f9f04 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile +++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile @@ -9,12 +9,6 @@ end require 'rake' require 'rake/rdoctask' -<% unless options[:skip_test_unit] -%> -<%= rakefile_test_tasks %> - -task :default => :test -<% end -%> - Rake::RDocTask.new(:rdoc) do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = '<%= camelized %>' diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt index 91d9cf079d..ebd5a77dd5 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt +++ b/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt @@ -2,4 +2,4 @@ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. ENGINE_PATH = File.expand_path('../..', __FILE__) -load File.expand_path('../../<%= test_path %>/dummy/script/rails', __FILE__) +load File.expand_path('../../<%= dummy_path %>/script/rails', __FILE__) diff --git a/railties/test/fixtures/lib/create_test_dummy_template.rb b/railties/test/fixtures/lib/create_test_dummy_template.rb new file mode 100644 index 0000000000..e4378bbd1a --- /dev/null +++ b/railties/test/fixtures/lib/create_test_dummy_template.rb @@ -0,0 +1 @@ +create_dummy_app("spec/dummy") diff --git a/railties/test/fixtures/lib/plugin_builders/spec_builder.rb b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb index bdaa1fb8e1..aa18c7ddaa 100644 --- a/railties/test/fixtures/lib/plugin_builders/spec_builder.rb +++ b/railties/test/fixtures/lib/plugin_builders/spec_builder.rb @@ -1,13 +1,19 @@ class PluginBuilder < Rails::PluginBuilder def test create_file "spec/spec_helper.rb" + append_file "Rakefile", <<-EOF +# spec tasks in rakefile + +task :default => :spec + EOF end - def test_path - "spec" + def generate_test_dummy + dummy_path("spec/dummy") + super end - def rakefile_test_tasks - "# spec tasks in rakefile" + def skip_test_unit? + true end end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index 6b7095ba78..f7f4f0261f 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -56,6 +56,13 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_no_match /It works from file!.*It works_from_file/, run_generator([destination_root, "-m", "lib/template.rb"]) end + def test_ensure_that_test_dummy_can_be_generated_from_a_template + FileUtils.cd(Rails.root) + run_generator([destination_root, "-m", "lib/create_test_dummy_template.rb", "--skip-test-unit"]) + assert_file "spec/dummy" + assert_no_file "test" + end + def test_database_entry_is_assed_by_default_in_full_mode run_generator([destination_root, "--full"]) assert_file "test/dummy/config/database.yml", /sqlite/ @@ -143,9 +150,9 @@ class CustomPluginGeneratorTest < Rails::Generators::TestCase FileUtils.cd(destination_root) run_generator([destination_root, "-b", "#{Rails.root}/lib/plugin_builders/spec_builder.rb"]) assert_file 'spec/spec_helper.rb' + assert_file 'spec/dummy' assert_file 'Rakefile', /task :default => :spec/ assert_file 'Rakefile', /# spec tasks in rakefile/ - assert_file 'spec/dummy' assert_file 'script/rails', %r{spec/dummy} end From c159b501b0743928bda6a9d0609c263e50691676 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 15:44:07 +0100 Subject: [PATCH 32/36] Add example rake task to 'plugin new' generator --- .../rails/generators/rails/plugin_new/plugin_new_generator.rb | 1 + .../rails/plugin_new/templates/lib/tasks/%name%_tasks.rake | 4 ++++ railties/test/generators/plugin_new_generator_test.rb | 1 + 3 files changed, 6 insertions(+) create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index eac4f76510..b8408a0f9b 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -29,6 +29,7 @@ module Rails def lib template "lib/%name%.rb" + template "lib/tasks/%name%_tasks.rake" if full? template "lib/%name%/engine.rb" end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake b/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake new file mode 100644 index 0000000000..7121f5ae23 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/tasks/%name%_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :<%= name %> do +# # Task goes here +# end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index f7f4f0261f..c66b0024e5 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -11,6 +11,7 @@ DEFAULT_PLUGIN_FILES = %w( MIT-LICENSE lib lib/bukkits.rb + lib/tasks/bukkits_tasks.rake script/rails test/bukkits_test.rb test/test_helper.rb From cbe391b517f55caad8cbefa6f864289d76fab653 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Nov 2010 16:34:07 +0100 Subject: [PATCH 33/36] Add --mountable option to 'plugin new' generator which generates full mountable application (engine) --- .../rails/plugin_new/plugin_new_generator.rb | 28 +++++++++++++++++-- .../%name%/application_controller.rb.tt | 4 +++ .../helpers/%name%/application_helper.rb.tt | 4 +++ .../plugin_new/templates/config/routes.rb | 3 ++ .../plugin_new/templates/lib/%name%/engine.rb | 3 ++ .../plugin_new/templates/rails/routes.rb | 4 +++ .../generators/plugin_new_generator_test.rb | 9 ++++++ 7 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb create mode 100644 railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index b8408a0f9b..d4706063f3 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -7,6 +7,10 @@ module Rails template "Rakefile" end + def app + directory "app" if options[:mountable] + end + def readme copy_file "README.rdoc" end @@ -35,6 +39,10 @@ module Rails end end + def config + template "config/routes.rb" if mountable? + end + def test template "test/test_helper.rb" template "test/%name%_test.rb" @@ -59,6 +67,9 @@ task :default => :test def test_dummy_config template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true + if mountable? + template "rails/routes.rb", "#{dummy_path}/config/routes.rb", :force => true + end end def test_dummy_clean @@ -91,8 +102,11 @@ task :default => :test alias_method :plugin_path, :app_path - class_option :full, :type => :boolean, :default => false, - :desc => "Generate rails engine with integration tests" + class_option :full, :type => :boolean, :default => false, + :desc => "Generate rails engine with integration tests" + + class_option :mountable, :type => :boolean, :default => false, + :desc => "Generate mountable isolated application" def initialize(*args) raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank? @@ -111,6 +125,10 @@ task :default => :test build(:gemfile) unless options[:skip_gemfile] end + def create_app_files + build(:app) + end + def create_config_files build(:config) end @@ -154,7 +172,11 @@ task :default => :test end def full? - options[:full] + options[:full] || options[:mountable] + end + + def mountable? + options[:mountable] end def self.banner diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt new file mode 100644 index 0000000000..f225bc9f7f --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/app/controllers/%name%/application_controller.rb.tt @@ -0,0 +1,4 @@ +module <%= camelized %> + class ApplicationController < ActiveController::Base + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt b/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt new file mode 100644 index 0000000000..40ae9f52c2 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/app/helpers/%name%/application_helper.rb.tt @@ -0,0 +1,4 @@ +module <%= camelized %> + module ApplicationHelper + end +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb b/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb new file mode 100644 index 0000000000..42ddf380d8 --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/config/routes.rb @@ -0,0 +1,3 @@ +<%= camelized %>::Engine.routes.draw do + +end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb index 779bd1cfd3..9600ee0c3f 100644 --- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb +++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%/engine.rb @@ -1,4 +1,7 @@ module <%= camelized %> class Engine < Rails::Engine +<% if mountable? -%> + isolate_namespace <%= camelized %> +<% end -%> end end diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb b/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb new file mode 100644 index 0000000000..730ee31c3d --- /dev/null +++ b/railties/lib/rails/generators/rails/plugin_new/templates/rails/routes.rb @@ -0,0 +1,4 @@ +Rails.application.routes.draw do + + mount <%= camelized %>::Engine => "/<%= name %>" +end diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index c66b0024e5..a59013b061 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -131,6 +131,15 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_no_match /create\s+config\/application.rb/, run_generator end + def test_create_mountable_application_with_mountable_option + run_generator [destination_root, "--mountable"] + assert_file "config/routes.rb", /Bukkits::Engine.routes.draw do/ + assert_file "lib/bukkits/engine.rb", /isolate_namespace Bukkits/ + assert_file "test/dummy/config/routes.rb", /mount Bukkits::Engine => "\/bukkits"/ + assert_file "app/controllers/bukkits/application_controller.rb", /module Bukkits\n class ApplicationController < ActiveController::Base/ + assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/ + end + protected def action(*args, &block) From d0d30e767d7e9a61ec1d8b8d44894f0ab508b990 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 3 Nov 2010 20:12:08 +0100 Subject: [PATCH 34/36] Fix scaffold generator to be aware of namespace in isolated engine --- .../erb/scaffold/templates/_form.html.erb | 2 + .../erb/scaffold/templates/edit.html.erb | 2 + .../erb/scaffold/templates/index.html.erb | 2 + .../erb/scaffold/templates/new.html.erb | 2 + .../erb/scaffold/templates/show.html.erb | 2 + railties/lib/rails/generators/named_base.rb | 8 +- .../rails/resource/resource_generator.rb | 4 +- .../templates/controller.rb | 2 + .../lib/rails/generators/resource_helpers.rb | 4 +- .../scaffold/templates/functional_test.rb | 2 + .../generators/namespaced_generators_test.rb | 153 ++++++++++++++++++ 11 files changed, 178 insertions(+), 5 deletions(-) diff --git a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb index d12b2ff0e5..c8ee939ad7 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/_form.html.erb @@ -1,3 +1,4 @@ +<% without_namespacing do -%> <%%= form_for(@<%= singular_table_name %>) do |f| %> <%% if @<%= singular_table_name %>.errors.any? %>
@@ -21,3 +22,4 @@ <%%= f.submit %>
<%% end %> +<% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb index e58b9fbd08..d1bfcbc429 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/edit.html.erb @@ -1,6 +1,8 @@ +<% without_namespacing do -%>

Editing <%= singular_table_name %>

<%%= render 'form' %> <%%= link_to 'Show', @<%= singular_table_name %> %> | <%%= link_to 'Back', <%= index_helper %>_path %> +<% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb index 4c46db4d67..435d126ee4 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb @@ -1,3 +1,4 @@ +<% without_namespacing do -%>

Listing <%= plural_table_name %>

@@ -25,3 +26,4 @@
<%%= link_to 'New <%= human_name %>', new_<%= singular_table_name %>_path %> +<% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb index 02ae4d015e..fe4d0971c4 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/new.html.erb @@ -1,5 +1,7 @@ +<% without_namespacing do -%>

New <%= singular_table_name %>

<%%= render 'form' %> <%%= link_to 'Back', <%= index_helper %>_path %> +<% end -%> diff --git a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb index c0e5ccff1e..bc3a87b99f 100644 --- a/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb +++ b/railties/lib/rails/generators/erb/scaffold/templates/show.html.erb @@ -1,3 +1,4 @@ +<% without_namespacing do -%>

<%%= notice %>

<% for attribute in attributes -%> @@ -10,3 +11,4 @@ <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>) %> | <%%= link_to 'Back', <%= index_helper %>_path %> +<% end -%> diff --git a/railties/lib/rails/generators/named_base.rb b/railties/lib/rails/generators/named_base.rb index 9131a19043..badf981d05 100644 --- a/railties/lib/rails/generators/named_base.rb +++ b/railties/lib/rails/generators/named_base.rb @@ -30,9 +30,15 @@ module Rails end end + def without_namespacing(&block) + inside_namespace do + concat(capture(&block)) + end + end + def indent(content, multiplier = 2) spaces = " " * multiplier - content.each_line.map {|line| "#{spaces}#{line}" }.join("\n") + content = content.each_line.map {|line| "#{spaces}#{line}" }.join end def wrap_with_namespace(content) diff --git a/railties/lib/rails/generators/rails/resource/resource_generator.rb b/railties/lib/rails/generators/rails/resource/resource_generator.rb index 8a943013d3..c7345f3cfb 100644 --- a/railties/lib/rails/generators/rails/resource/resource_generator.rb +++ b/railties/lib/rails/generators/rails/resource/resource_generator.rb @@ -16,9 +16,9 @@ module Rails def add_resource_route return if options[:actions].present? - route_config = class_path.collect{|namespace| "namespace :#{namespace} do " }.join(" ") + route_config = regular_class_path.collect{|namespace| "namespace :#{namespace} do " }.join(" ") route_config << "resources :#{file_name.pluralize}" - route_config << " end" * class_path.size + route_config << " end" * regular_class_path.size route route_config end end diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb index b21340f755..b5317a055b 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb @@ -1,3 +1,4 @@ +<% module_namespacing do -%> class <%= controller_class_name %>Controller < ApplicationController # GET <%= route_url %> # GET <%= route_url %>.xml @@ -81,3 +82,4 @@ class <%= controller_class_name %>Controller < ApplicationController end end end +<% end -%> diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 829f4b200a..c9e70468a1 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -34,7 +34,7 @@ module Rails attr_reader :controller_name def controller_class_path - @class_path + class_path end def controller_file_name @@ -46,7 +46,7 @@ module Rails end def controller_class_name - @controller_class_name ||= (controller_class_path + [controller_file_name]).map!{ |m| m.camelize }.join('::') + (controller_class_path + [controller_file_name]).map!{ |m| m.camelize }.join('::') end def controller_i18n_scope diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb index f23e495450..964d59d84c 100644 --- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb +++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb @@ -1,5 +1,6 @@ require 'test_helper' +<% module_namespacing do -%> class <%= controller_class_name %>ControllerTest < ActionController::TestCase setup do @<%= singular_table_name %> = <%= table_name %>(:one) @@ -47,3 +48,4 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase assert_redirected_to <%= index_helper %>_path end end +<% end -%> diff --git a/railties/test/generators/namespaced_generators_test.rb b/railties/test/generators/namespaced_generators_test.rb index d1190fd17d..d61a02d32f 100644 --- a/railties/test/generators/namespaced_generators_test.rb +++ b/railties/test/generators/namespaced_generators_test.rb @@ -3,6 +3,7 @@ require 'rails/generators/rails/controller/controller_generator' require 'rails/generators/rails/model/model_generator' require 'rails/generators/rails/observer/observer_generator' require 'rails/generators/mailer/mailer_generator' +require 'rails/generators/rails/scaffold/scaffold_generator' class NamespacedGeneratorTestCase < Rails::Generators::TestCase def setup @@ -202,3 +203,155 @@ class NamespacedMailerGeneratorTest < NamespacedGeneratorTestCase assert_file "app/views/test_app/notifier" end end + +class NamespacedScaffoldGeneratorTest < NamespacedGeneratorTestCase + include GeneratorsTestHelper + arguments %w(product_line title:string price:integer) + tests Rails::Generators::ScaffoldGenerator + + setup :copy_routes + + def test_scaffold_on_invoke + run_generator + + # Model + assert_file "app/models/test_app/product_line.rb", /module TestApp\n class ProductLine < ActiveRecord::Base/ + assert_file "test/unit/test_app/product_line_test.rb", /module TestApp\n class ProductLineTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/test_app/product_lines.yml" + assert_migration "db/migrate/create_test_app_product_lines.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_match(/resources :product_lines$/, route) + end + + # Controller + assert_file "app/controllers/test_app/product_lines_controller.rb" do |content| + assert_match(/module TestApp\n class ProductLinesController < ApplicationController/, content) + end + + assert_file "test/functional/test_app/product_lines_controller_test.rb", + /module TestApp\n class ProductLinesControllerTest < ActionController::TestCase/ + + # Views + %w( + index + edit + new + show + _form + ).each { |view| assert_file "app/views/test_app/product_lines/#{view}.html.erb" } + assert_no_file "app/views/layouts/test_app/product_lines.html.erb" + + # Helpers + assert_file "app/helpers/test_app/product_lines_helper.rb" + assert_file "test/unit/helpers/test_app/product_lines_helper_test.rb" + + # Stylesheets + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_on_revoke + run_generator + run_generator ["product_line"], :behavior => :revoke + + # Model + assert_no_file "app/models/test_app/product_line.rb" + assert_no_file "test/unit/test_app/product_line_test.rb" + assert_no_file "test/fixtures/test_app/product_lines.yml" + assert_no_migration "db/migrate/create_test_app_product_lines.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_no_match(/resources :product_lines$/, route) + end + + # Controller + assert_no_file "app/controllers/test_app/product_lines_controller.rb" + assert_no_file "test/functional/test_app/product_lines_controller_test.rb" + + # Views + assert_no_file "app/views/test_app/product_lines" + assert_no_file "app/views/test_app/layouts/product_lines.html.erb" + + # Helpers + assert_no_file "app/helpers/test_app/product_lines_helper.rb" + assert_no_file "test/unit/helpers/test_app/product_lines_helper_test.rb" + + # Stylesheets (should not be removed) + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_with_namespace_on_invoke + run_generator [ "admin/role", "name:string", "description:string" ] + + # Model + assert_file "app/models/test_app/admin.rb", /module TestApp\n module Admin/ + assert_file "app/models/test_app/admin/role.rb", /module TestApp\n class Admin::Role < ActiveRecord::Base/ + assert_file "test/unit/test_app/admin/role_test.rb", /module TestApp\n class Admin::RoleTest < ActiveSupport::TestCase/ + assert_file "test/fixtures/test_app/admin/roles.yml" + assert_migration "db/migrate/create_test_app_admin_roles.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_match(/namespace :admin do resources :roles end$/, route) + end + + # Controller + assert_file "app/controllers/test_app/admin/roles_controller.rb" do |content| + assert_match(/module TestApp\n class Admin::RolesController < ApplicationController/, content) + end + + assert_file "test/functional/test_app/admin/roles_controller_test.rb", + /module TestApp\n class Admin::RolesControllerTest < ActionController::TestCase/ + + # Views + %w( + index + edit + new + show + _form + ).each { |view| assert_file "app/views/test_app/admin/roles/#{view}.html.erb" } + assert_no_file "app/views/layouts/admin/roles.html.erb" + + # Helpers + assert_file "app/helpers/test_app/admin/roles_helper.rb" + assert_file "test/unit/helpers/test_app/admin/roles_helper_test.rb" + + # Stylesheets + assert_file "public/stylesheets/scaffold.css" + end + + def test_scaffold_with_namespace_on_revoke + run_generator [ "admin/role", "name:string", "description:string" ] + run_generator [ "admin/role" ], :behavior => :revoke + + # Model + assert_file "app/models/test_app/admin.rb" # ( should not be remove ) + assert_no_file "app/models/test_app/admin/role.rb" + assert_no_file "test/unit/test_app/admin/role_test.rb" + assert_no_file "test/fixtures/test_app/admin/roles.yml" + assert_no_migration "db/migrate/create_test_app_admin_roles.rb" + + # Route + assert_file "config/routes.rb" do |route| + assert_no_match(/namespace :admin do resources :roles end$/, route) + end + + # Controller + assert_no_file "app/controllers/test_app/admin/roles_controller.rb" + assert_no_file "test/functional/test_app/admin/roles_controller_test.rb" + + # Views + assert_no_file "app/views/test_app/admin/roles" + assert_no_file "app/views/layouts/test_app/admin/roles.html.erb" + + # Helpers + assert_no_file "app/helpers/test_app/admin/roles_helper.rb" + assert_no_file "test/unit/helpers/test_app/admin/roles_helper_test.rb" + + # Stylesheets (should not be removed) + assert_file "public/stylesheets/scaffold.css" + end +end From 1fd46240a61efa72c2e1259fbeafae5cfd8a6df9 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 4 Nov 2010 20:04:57 +0100 Subject: [PATCH 35/36] New version of thor was released no need to use the one from git --- Gemfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gemfile b/Gemfile index ac9c63790c..66a446a177 100644 --- a/Gemfile +++ b/Gemfile @@ -6,8 +6,6 @@ else gem "arel", :git => "git://github.com/rails/arel.git" end -gem "thor", :git => "git://github.com/wycats/thor.git" - gem "rack", :git => "git://github.com/rack/rack.git" gem "rails", :path => File.dirname(__FILE__) From cc135e3b6df1785852de2470b4b93559c88c891e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 8 Nov 2010 22:43:51 +0100 Subject: [PATCH 36/36] Allow to set dummy application path through options --- .../generators/rails/plugin_new/plugin_new_generator.rb | 5 ++++- railties/test/generators/plugin_new_generator_test.rb | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb index d4706063f3..8fac6fc70a 100644 --- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb +++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb @@ -102,6 +102,9 @@ task :default => :test alias_method :plugin_path, :app_path + class_option :dummy_path, :type => :string, :default => "test/dummy", + :desc => "Create dummy application at given path" + class_option :full, :type => :boolean, :default => false, :desc => "Generate rails engine with integration tests" @@ -232,7 +235,7 @@ end def dummy_path(path = nil) @dummy_path = path if path - @dummy_path || "test/dummy" + @dummy_path || options[:dummy_path] end def mute(&block) diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb index a59013b061..8dc5ca90ba 100644 --- a/railties/test/generators/plugin_new_generator_test.rb +++ b/railties/test/generators/plugin_new_generator_test.rb @@ -140,6 +140,13 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase assert_file "app/helpers/bukkits/application_helper.rb", /module Bukkits\n module ApplicationHelper/ end + def test_passing_dummy_path_as_a_parameter + run_generator [destination_root, "--dummy_path", "spec/dummy"] + assert_file "spec/dummy" + assert_file "spec/dummy/config/application.rb" + assert_no_file "test/dummy" + end + protected def action(*args, &block)