From 52f2f9810eaf3d385ca3eef8ed6fc62e4fd1f7d3 Mon Sep 17 00:00:00 2001 From: Dharam Gollapudi Date: Fri, 13 Nov 2015 16:58:51 -0800 Subject: [PATCH] Implement Rake proxy for Rails' command line interface. Allows any Rake task to be run through `bin/rails` such as `bin/rails db:migrate`, `bin/rails notes` etc. The Rake tasks are appended to Rails' help output, and blend in as standard commands. --- guides/source/initialization.md | 12 +++--- railties/lib/rails/commands.rb | 2 +- railties/lib/rails/commands/commands_tasks.rb | 14 +++++++ railties/lib/rails/commands/rake_proxy.rb | 42 +++++++++++++++++++ 4 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 railties/lib/rails/commands/rake_proxy.rb diff --git a/guides/source/initialization.md b/guides/source/initialization.md index ebe1cb206a..1215931465 100644 --- a/guides/source/initialization.md +++ b/guides/source/initialization.md @@ -139,7 +139,8 @@ aliases = { "c" => "console", "s" => "server", "db" => "dbconsole", - "r" => "runner" + "r" => "runner", + "t" => "test" } command = ARGV.shift @@ -158,19 +159,20 @@ defined here to find the matching command. ### `rails/commands/command_tasks.rb` -When one types an incorrect rails command, the `run_command` is responsible for -throwing an error message. If the command is valid, a method of the same name -is called. +If the command is part of the COMMAND_WHITELIST, a method of the same name is called, +if not we proxy it to rake. ```ruby COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole application runner new version help) def run_command!(command) command = parse_command(command) + if COMMAND_WHITELIST.include?(command) send(command) else - write_error_message(command) + ARGV.unshift(command) + send(:rake) end end ``` diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb index b9c4e02ca0..7627fcf5a0 100644 --- a/railties/lib/rails/commands.rb +++ b/railties/lib/rails/commands.rb @@ -7,7 +7,7 @@ "s" => "server", "db" => "dbconsole", "r" => "runner", - "t" => "test", + "t" => "test" } command = ARGV.shift diff --git a/railties/lib/rails/commands/commands_tasks.rb b/railties/lib/rails/commands/commands_tasks.rb index 7e6b49e2a3..e1713d5798 100644 --- a/railties/lib/rails/commands/commands_tasks.rb +++ b/railties/lib/rails/commands/commands_tasks.rb @@ -1,3 +1,5 @@ +require 'rails/commands/rake_proxy' + module Rails # This is a class which takes in a rails command and initiates the appropriate # initiation sequence. @@ -5,6 +7,8 @@ module Rails # Warning: This class mutates ARGV because some commands require manipulating # it before they are run. class CommandsTasks # :nodoc: + include Rails::RakeProxy + attr_reader :argv HELP_MESSAGE = <<-EOT @@ -26,6 +30,7 @@ class CommandsTasks # :nodoc: runner Run a piece of code in the application environment (short-cut alias: "r") All commands can be run with -h (or --help) for more information. + EOT COMMAND_WHITELIST = %w(plugin generate destroy console server dbconsole runner new version help test) @@ -39,6 +44,9 @@ def run_command!(command) if COMMAND_WHITELIST.include?(command) send(command) + else + ARGV.unshift(command) + send(:rake) end end @@ -102,6 +110,10 @@ def new end end + def rake + invoke_rake + end + def version argv.unshift '--version' require_command!("application") @@ -109,6 +121,8 @@ def version def help write_help_message + write_rake_tasks_help_message + write_rake_tasks end private diff --git a/railties/lib/rails/commands/rake_proxy.rb b/railties/lib/rails/commands/rake_proxy.rb new file mode 100644 index 0000000000..13a9aef694 --- /dev/null +++ b/railties/lib/rails/commands/rake_proxy.rb @@ -0,0 +1,42 @@ +require 'rake' + +module Rails + module RakeProxy #:nodoc: + + RAKE_TASKS_HELP_MESSAGE = <<-EOT +In addition to those, you can run the rake tasks as rails commands: + + EOT + + private + + def write_rake_tasks_help_message + puts RAKE_TASKS_HELP_MESSAGE + end + + def write_rake_tasks + width = rake_tasks.map { |t| t.name_with_args.length }.max || 10 + rake_tasks.each do |t| + printf("#{Rake.application.name} %-#{width}s # %s\n", t.name_with_args, t.comment) + end + end + + def rake_tasks + return @rake_tasks if defined?(@rake_tasks) + + require_application_and_environment! + Rake::TaskManager.record_task_metadata = true + Rake.application.instance_variable_set(:@name, 'rails') + Rails.application.load_tasks + @rake_tasks = Rake.application.tasks.select(&:comment) + end + + def invoke_rake + Rake.application.standard_exception_handling do + Rake.application.init('rails') + Rake.application.load_rakefile + Rake.application.top_level + end + end + end +end -- GitLab