diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 6cb88ca01d..b2208193d2 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Make every Rails command work within engines. + + *Sean Collins*, *Yuji Yaginuma* + * Don't generate HTML/ERB templates for scaffold controller with `--api` flag. Fixes #27591. diff --git a/railties/lib/rails/command/actions.rb b/railties/lib/rails/command/actions.rb index 31b656ec31..fb80e9d997 100644 --- a/railties/lib/rails/command/actions.rb +++ b/railties/lib/rails/command/actions.rb @@ -11,6 +11,11 @@ module Rails if defined?(ENGINE_PATH) def require_application_and_environment! require ENGINE_PATH + + if defined?(APP_PATH) + require APP_PATH + Rails.application.require_environment! + end end def load_tasks diff --git a/railties/lib/rails/commands/help/USAGE b/railties/lib/rails/commands/help/USAGE index 348f41861f..c5f8ab72bb 100644 --- a/railties/lib/rails/commands/help/USAGE +++ b/railties/lib/rails/commands/help/USAGE @@ -1,16 +1,3 @@ -Usage: bin/rails COMMAND [args] [options] -<% if engine? %> -The common Rails commands available for engines are: - generate Generate new code (short-cut alias: "g") - destroy Undo code generated with "generate" (short-cut alias: "d") - test Run tests (short-cut alias: "t") - -All commands can be run with -h for more information. - -If you want to run any commands that need to be run in context -of the application, like `bin/rails server` or `bin/rails console`, -you should do it from the application's directory (typically test/dummy). -<% else %> The most common rails commands are: generate Generate new code (short-cut alias: "g") console Start the Rails console (short-cut alias: "c") @@ -18,10 +5,11 @@ The most common rails commands are: test Run tests (short-cut alias: "t") dbconsole Start a console for the database specified in config/database.yml (short-cut alias: "db") +<% unless engine? %> new Create a new Rails application. "rails new my_app" creates a new application called MyApp in "./my_app" +<% end %> All commands can be run with -h (or --help) for more information. -<% end %> In addition to those commands, there are: diff --git a/railties/lib/rails/commands/server/server_command.rb b/railties/lib/rails/commands/server/server_command.rb index 15c636103b..d58721f648 100644 --- a/railties/lib/rails/commands/server/server_command.rb +++ b/railties/lib/rails/commands/server/server_command.rb @@ -95,7 +95,7 @@ module Rails module Command class ServerCommand < Base # :nodoc: - DEFAULT_PID_PATH = File.expand_path("tmp/pids/server.pid").freeze + DEFAULT_PID_PATH = "tmp/pids/server.pid".freeze class_option :port, aliases: "-p", type: :numeric, desc: "Runs Rails on the specified port.", banner: :port, default: 3000 @@ -141,7 +141,7 @@ module Rails config: options[:config], environment: environment, daemonize: options[:daemon], - pid: options[:pid], + pid: pid, caching: options["dev-caching"], restart_cmd: restart_command } @@ -165,6 +165,10 @@ module Rails "bin/rails server #{@server} #{@original_options.join(" ")}" end + def pid + File.expand_path(options[:pid]) + end + def self.banner(*) "rails server [puma, thin etc] [options]" end diff --git a/railties/lib/rails/engine/commands.rb b/railties/lib/rails/engine/commands.rb index a23ae44b0b..b9ef63243a 100644 --- a/railties/lib/rails/engine/commands.rb +++ b/railties/lib/rails/engine/commands.rb @@ -1,12 +1,7 @@ -require "rails/command" +unless defined?(APP_PATH) + if File.exist?(File.expand_path("test/dummy/config/application.rb", ENGINE_ROOT)) + APP_PATH = File.expand_path("test/dummy/config/application", ENGINE_ROOT) + end +end -aliases = { - "g" => "generate", - "d" => "destroy", - "t" => "test" -} - -command = ARGV.shift -command = aliases[command] || command - -Rails::Command.invoke command, ARGV +require "rails/commands" diff --git a/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt index 56e7925c6b..c03d9953d4 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt +++ b/railties/lib/rails/generators/rails/plugin/templates/bin/rails.tt @@ -3,6 +3,7 @@ ENGINE_ROOT = File.expand_path('../..', __FILE__) ENGINE_PATH = File.expand_path('../../lib/<%= namespaced_name -%>/engine', __FILE__) +APP_PATH = File.expand_path('../../<%= dummy_path -%>/config/application', __FILE__) # Set up gems listed in the Gemfile. ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb index 527529aa52..e3dfc3e82b 100644 --- a/railties/test/commands/server_test.rb +++ b/railties/test/commands/server_test.rb @@ -122,11 +122,11 @@ class Rails::ServerTest < ActiveSupport::TestCase end def test_default_options - old_default_options = parse_arguments + server = Rails::Server.new + old_default_options = server.default_options Dir.chdir("..") do - default_options = parse_arguments - assert_equal old_default_options, default_options + assert_equal old_default_options, server.default_options end end diff --git a/railties/test/engine/commands_tasks_test.rb b/railties/test/engine/commands_tasks_test.rb deleted file mode 100644 index 817175b9ef..0000000000 --- a/railties/test/engine/commands_tasks_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "abstract_unit" - -class Rails::Engine::CommandsTasksTest < ActiveSupport::TestCase - def setup - @destination_root = Dir.mktmpdir("bukkits") - Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` } - end - - def teardown - FileUtils.rm_rf(@destination_root) - end - - def test_help_command_work_inside_engine - output = capture(:stderr) do - Dir.chdir(plugin_path) { `bin/rails --help` } - end - assert_no_match "NameError", output - end - - private - def plugin_path - "#{@destination_root}/bukkits" - end -end diff --git a/railties/test/engine/commands_test.rb b/railties/test/engine/commands_test.rb new file mode 100644 index 0000000000..b1c937143f --- /dev/null +++ b/railties/test/engine/commands_test.rb @@ -0,0 +1,96 @@ +require "abstract_unit" +begin + require "pty" +rescue LoadError +end + +class Rails::Engine::CommandsTest < ActiveSupport::TestCase + def setup + @destination_root = Dir.mktmpdir("bukkits") + Dir.chdir(@destination_root) { `bundle exec rails plugin new bukkits --mountable` } + end + + def teardown + FileUtils.rm_rf(@destination_root) + end + + def test_help_command_work_inside_engine + output = capture(:stderr) do + Dir.chdir(plugin_path) { `bin/rails --help` } + end + assert_no_match "NameError", output + end + + def test_runner_command_work_inside_engine + output = capture(:stdout) do + Dir.chdir(plugin_path) { system("bin/rails runner 'puts Rails.env'") } + end + + assert_equal "test", output.strip + end + + def test_console_command_work_inside_engine + skip "PTY unavailable" unless available_pty? + + master, slave = PTY.open + spawn_command("console", slave) + assert_output(">", master) + ensure + master.puts "quit" + end + + def test_dbconsole_command_work_inside_engine + skip "PTY unavailable" unless available_pty? + + master, slave = PTY.open + spawn_command("dbconsole", slave) + assert_output("sqlite>", master) + ensure + master.puts ".exit" + end + + def test_server_command_work_inside_engine + skip "PTY unavailable" unless available_pty? + + master, slave = PTY.open + pid = spawn_command("server", slave) + assert_output("Listening on", master) + ensure + kill(pid) + end + + private + def plugin_path + "#{@destination_root}/bukkits" + end + + def assert_output(expected, io, timeout = 10) + timeout = Time.now + timeout + + output = "" + until output.include?(expected) || Time.now > timeout + if IO.select([io], [], [], 0.1) + output << io.read(1) + end + end + + assert_includes output, expected, "#{expected.inspect} expected, but got:\n\n#{output}" + end + + def spawn_command(command, fd) + Process.spawn( + "#{plugin_path}/bin/rails #{command}", + in: fd, out: fd, err: fd + ) + end + + def available_pty? + defined?(PTY) && PTY.respond_to?(:open) + end + + def kill(pid) + Process.kill("TERM", pid) + Process.wait(pid) + rescue Errno::ESRCH + end +end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 9921a80342..ddfbc1a698 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -421,6 +421,7 @@ class PluginGeneratorTest < Rails::Generators::TestCase run_generator [destination_root, "--full"] assert_file "bin/rails", /ENGINE_PATH = File.expand_path\('..\/..\/lib\/bukkits\/engine', __FILE__\)/ assert_file "bin/rails", /ENGINE_ROOT = File.expand_path\('..\/..', __FILE__\)/ + assert_file "bin/rails", %r|APP_PATH = File.expand_path\('../../test/dummy/config/application', __FILE__\)| assert_file "bin/rails", /require 'rails\/all'/ assert_file "bin/rails", /require 'rails\/engine\/commands'/ end