Skip to content
New issue

Have a question about this project?Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of serviceand privacy statement.We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib/commands/*_command.rbshould load custom Thor commands #50193

Open
bensheldonopened this issue Nov 28, 2023 · 6 comments · May be fixed by#50218
Open

lib/commands/*_command.rbshould load custom Thor commands #50193

bensheldonopened this issue Nov 28, 2023 · 6 comments · May be fixed by#50218

Comments

@bensheldon
Copy link
Contributor

bensheldon commented Nov 28, 2023

Expected behavior

I should be able to create custom Rails Thor commands for my application in a way that is analogous to adding custom Rake tasks:

Rake Task Thor Command
Rails.root/lib/tasks/custom.task Rails.root/lib/commands/custom_command.rb

For example, this should create the custom command$ bin/rails custom:somethingwith all of the Thor niceties:

# lib/commands/custom_command.rb
moduleRails
moduleCommand
classCustomCommand<Base
desc"something","Perform a custom task"
method_option:nice,type::boolean,desc:"Thor args are nice"
defsomething
puts"Custom task performed!"
end
end
end
end

This behavior already works for Rails Engines (aside: maybe the engine generator should automatically create alib/commandsdirectory in addition tolib/tasks). Here's where those lookups happen:

deflookup_paths#:doc:
@lookup_paths||=%w(rails/commandscommands)
end
deffile_lookup_paths#:doc:
@file_lookup_paths||=["{#{lookup_paths.join(',')}} ","**","*_command.rb"]
end

These are loaded via the$LOAD_PATH,for a specific command:

deflookup(namespaces)
paths=namespaces_to_paths(namespaces)
paths.eachdo|raw_path|
lookup_paths.eachdo|base|
path="#{base}/#{raw_path}_#{command_type}"
begin
requirepath
return

... or all commands forhelp:

# This will try to load any command in the load path to show in help.
deflookup!
$LOAD_PATH.eachdo|base|
Dir[File.join(base,*file_lookup_paths)].eachdo|path|
path=path.delete_prefix("#{base}/ ")
requirepath

Actual behavior

TheRails.root/libdirectory does not get added to the $LOAD_PATH before those lookups happen, so they're never loaded and the commands are not found.

I think the simple solution here is to make sure thatRails.root/libis added to the$LOAD_PATHwhen the$ railscommand is initially run. Thatnormallyhappens when the Application is required and there's a custom command method to do that:require_application!,but I imagine there could be reasons why that's done selectively. Hence opening an issue in case someone has better ideas.

The "add lib to $LOAD_PATH" behavior was most recently solidified in#48596

System configuration

Rails version:7.1.1

@bensheldon
Copy link
Contributor Author

I looked at this with@matthewdand we think this will work:

diff --git a/railties/lib/rails/command.rb b/railties/lib/rails/command.rb
--- a/railties/lib/rails/command.rb
+++ b/railties/lib/rails/command.rb
@@ -65,7 +65,12 @@
full_namespace = full_namespace.to_s
namespace, command_name = split_namespace(full_namespace)
-command = find_by_namespace(namespace, command_name)

with_argv(args) do
+command = find_by_namespace(namespace, command_name)
+unless command && command.all_commands[command_name]
+require_application!
+command = find_by_namespace(namespace, command_name)
+end
+
if command && command.all_commands[command_name]
command.perform(command_name, args, config)

...now to write some tests.

@rails-bot
Copy link

rails-bot bot commented Feb 27, 2024

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the7-1-stablebranch or onmain,please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Feb 27, 2024
@bensheldon
Copy link
Contributor Author

Still on my todo, but open if anyone else gets to it.

@rails-bot rails-bot bot removed the stale label Feb 27, 2024
@mildred
Copy link

mildred commented Apr 17, 2024

In the meantime, adding this toconfig/boot.rbseems to work

$LOAD_PATH <<File.join(File.dirname(__dir__),'lib')

Although initialization of the application is not performed before command is executed

Edit: just addboot_application!to the command

@rails-bot
Copy link

rails-bot bot commented Jul 16, 2024

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the7-2-stablebranch or onmain,please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Jul 16, 2024
@skipkayhil skipkayhil removed the stale label Jul 16, 2024
@rails-bot
Copy link

rails-bot bot commented Oct 14, 2024

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the7-2-stablebranch or onmain,please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

@rails-bot rails-bot bot added the stale label Oct 14, 2024
@skipkayhil skipkayhil added pinned and removed stale labels Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants