Skip to content

Commit

Permalink
UnrecognizedCommandError can be corrected and retried.
Browse files Browse the repository at this point in the history
When encountering a UnrecognizedCommandError, the developer will be given the option to run of the suggested corrections instead.

Co-authored-by: Gannon McGibbon <gannon.mcgibbon@gmail.com>
  • Loading branch information
andrewn617 and gmcgibbon committed Apr 5, 2024
1 parent 84c4598 commit 81a2461
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
14 changes: 14 additions & 0 deletions railties/CHANGELOG.md
@@ -1,3 +1,17 @@
* When encountering an Unrecognized Command Error, the developer will be given the option to
run of the suggested corrections instead.

```txt
bin/rails action_txt:install
Unrecognized command "action_txt:install"
Did you mean? action_text:install [Yn] Y
Installing JavaScript dependencies
...
```

*Andrew Novoselac & Gannon McGibbon*

* Allow Actionable Errors encountered when running tests to be retried.

```txt
Expand Down
22 changes: 22 additions & 0 deletions railties/lib/rails/command.rb
Expand Up @@ -44,6 +44,21 @@ def initialize(name)
end
end

class UnrecognizedCommandCorrector < Thor::Shell::Basic
def correct(error)
if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
say error.original_message

error.corrections.detect do |correction|
correction if yes? DidYouMean.formatter.message_for([correction]) + " [Yn]"
end
else
say error.detailed_message
nil
end
end
end

include Behavior

HELP_MAPPINGS = %w(-h -? --help).to_set
Expand Down Expand Up @@ -76,6 +91,9 @@ def invoke(full_namespace, args = [], **config)
rescue UnrecognizedCommandError => error
if error.name == full_namespace && command && command_name == full_namespace
command.perform("help", [], config)
elsif tty?
correction = UnrecognizedCommandCorrector.new.correct(error)
return invoke(correction, args, **config) if correction
else
puts error.detailed_message
end
Expand Down Expand Up @@ -167,6 +185,10 @@ def lookup_paths # :doc:
def file_lookup_paths # :doc:
@file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_command.rb" ]
end

def tty?
STDOUT.tty?
end
end
end
end
25 changes: 23 additions & 2 deletions railties/test/command/help_integration_test.rb
Expand Up @@ -11,11 +11,32 @@ class Rails::Command::HelpIntegrationTest < ActiveSupport::TestCase
assert_match "Invoke default", rails("--trace")
end

test "prints helpful error on unrecognized command" do
test "prints helpful error on unrecognized command and allows command to be re-run" do
app_file("config/boot.rb", <<~RUBY, "a+")
require "rails/command"
module Rails
module Command
class UnrecognizedCommandCorrector
def yes?(statement, color = nil)
raise ArgumentError unless statement == "\nDid you mean? version [Yn]"
true
end
end
class << self
def tty?
true
end
end
end
end
RUBY

output = rails "vershen", allow_failure: true

assert_match %(Unrecognized command "vershen"), output
assert_match "Did you mean? version", output
assert_match Rails::VERSION::STRING, output
end

test "loads Rake tasks only once on unrecognized command" do
Expand Down

0 comments on commit 81a2461

Please sign in to comment.