NAME
Command::DynamicSubCommands - auto-generate sub-commands based on other classes
SYNOPSIS
# given that these classes exist:# Acme::Task::Foo# Acme::Task::Bar# in Acme/Worker/Command/DoTask.pm:class Acme::Worker::Command::DoTask {is => 'Command::DynamicSubCommands',has => [param1 => { is => 'Text' },param2 => { is => 'Text' },]};sub _sub_commands_from { 'Acme::Task' }sub execute {my $self = shift;print "this command " . ref($self) . " applies to " . $self->_target_class_name;return 1;}# the class above will discover them at compile,# and auto-generate these subclasses of itself:# Acme::Worker::Command::DoTask::Foo# Acme::Worker::Command::DoTask::Bar# in the shell...## $ acme worker do-task# foo# bar## $ acme worker do-task foo --param1 aaa --param2 bbb# this command Acme::Worker::Command::DoTask::Foo applies to Acme::Task::Foo## $ acme worker do-task bar --param1 ccc --param2 ddd# this command Acme::Worker::Command::DoTask::Bar applies to Acme::Task::Bar
DESCRIPTION
This module helps you avoid writing boilerplate commands.
When a command has a set of sub-commands which are meant to be derived from another group of classes, this module lets you auto-generate those sub-commands at run time.
REQUIRED ABSTRACT METHOD
- _sub_commands_from
-
$base_namespace = Acme::Order::Command->_sub_commands_from();# 'Acme::TaskReturns the namespace from which target classes will be discovered, andsub-commands will be generated.
PRIVATE API
- _target_class_name
-
$c= Acme::Order::Command::Purchasing->_target_class_name;# 'Acme::Task::Foo'The name of some class under the _sub_commands_from() namespace.This value is set during execute, revealing which sub-command the caller is using.
OPTIONAL OVERRIDES
- _build_sub_commmand
-
This can be overridden to customize the sub-command construction.By default, each target under _sub_commands_from will result ina call to this method. The default implementation is below:my $self = shift;my ($suggested_class_name,$delegator_class_name,$target_class_name) = @_;class {$suggested_class_name} {is => $delegator_class_name,sub_classify_by => 'class',has_constant => [_target_class_name => { value => $target_class_name },]};return ($suggested_class_name);Note that the class in question may be on the filesystem, and not needto be created. The return list can include more than one class name,or zero class names.
- _build_all_sub_commands
-
This is called once for any class which inherits from Command::DynamicSubCommands.It generates the sub-commands as needed, and returns a list.By default it resolves the target classes, and calls _build_sub_commandIt can be overridden to customize behavior, or filter results. Be sureto call @cmds = $self->SUPER::_build_all_sub_commands() if you wantto get the default commands in addition to overriding.
The sub-commands need not be 1:1 with the target classes, though this is the default.
The sub-commands need not inherit from the Command::DynamicSubCommands base command which generates them, though this is the default.