With a cli project I would like to have a shared super class with thor tasks. When calling the sub-command help it should expose the shared command with a custom description.
I came up with the code below, but the variable @plural is not substituted in the description.
Is this possible with Thor and some meta programming?
module MyModule
class ResourceSubcommand < Thor
def initialize(*args)
super
end
desc "list", "list all #{@plural}"
def list
list_object(@default_list_columns)
end
end
end
module MyModule
class Account < MyModule::ResourceSubcommand
def initialize(*args)
super
@plural = 'accounts'
end
end
end
module MyModule
class Commands < Thor
desc "account SUBCOMMAND ...ARGS", "manage Exact Online accounts"
subcommand "account", Account
end
end
running $ thorcli account help
should output:
Commands:
thorcli account help [COMMAND] # Describe subcommands or one specific subcommand
thorcli account list # list all accounts
The string passed to desc
is evaluated in the context of the class, but the initialize
method is evaluated in the context of instances, so the two @plural
belong to two different objects.
Further more, desc
is called immediately when defining the superclass MyModule::ResourceSubcommand
, and there is no easy way to postpone its evaluation after the superclass gets inherited and the @plural
in the subclass is set, your goal seems very hard to achieve.
P.S. I've tried overriding MyModule::ResourceSubcommand::inherited
, and MyModule::ResourceSubcommand.singleton_class::inherited
, and I failed. Maybe you could define MyModule::ResourceSubcommand
as a module, override its self.included
, and include it after setting @plural
in the subclass.
I finally succeed. Here is my solution:
module MyModule
# Change from class to module
module ResourceSubcommand
# A hook called when this module is included by other modules
def self.included(base)
base.class_eval do
desc "list", "list all #{@plural}"
def list
list_object(@default_list_columns)
end
end
end
end
end
module MyModule
# No inheritance
class Account
# Don't put this in any instance methods, including #initialize
@plural = 'accounts'
# Be sure to include after @plural is set
include ResourceSubcommand
end
end