Acme-CPANModulesBundle-Import-PerlDancerAdvent-2018
view release on metacpan or search on metacpan
devdata/http_advent.perldancer.org_2018_18 view on Meta::CPAN
<p>Dancer2 generates a skeleton that it useful for most developers, but if
you are a seasoned Dancer2 developer, you might have a set of
preferences not represented in the default skeleton.</p>
<p>If it's different file setup that you want to have, you could partially
achieve it with the <code>dancer2 gen -s DIRECTORY</code>, indicating a different
skeleton directory. But that doesn't fix all of it.</p>
<p>To have full control over the entire scaffolding operation, you will
need to have control of the command line implementation. Let me show
you how.</p>
<h2><a name="extending_in_a_class"></a>Extending in a class</h2>
<p>To extend the application in a class, you will need to write a new
class with a new command. That class will then need to be loaded in your
environment for you to enjoy it.</p>
<p>There are two options:</p>
<ul>
<li>
<p>Write a new distribution with your new module and install it locally. Done.</p>
</li>
<li>
<p>Write a new module and make the directory in which it sits available in
your <code>$PERL5LIB</code> environment variable.</p>
<p>This option is more useful for companies that have a big library
directory that is always available in the include directories list.</p>
<p>An example of this:</p>
<pre class="prettyprint"># Creating the directory
$ mkdir -p /opt/perl/lib/Dancer2/CLI/Command/
$ cd /opt/perl/lib/Dancer2/CLI/Command/
# Putting a mostly-empty file
$ echo -e "package Dancer2::CLI::Command::new;\n1;" >> new.pm
# Now making sure this path is in PERL5LIB
# (replace the bashrc file path with your system's path)
echo "export PERL5LIB="/opt/perl/lib/:$PERL5LIB" >> /etc/bash.bashrc</pre>
</li>
</ul>
<h2><a name="writing_your_own_command"></a>Writing your own command</h2>
<p><a href="https://metacpan.org/module/Dancer2">Dancer2</a> uses <a href="https://metacpan.org/module/App::Cmd">App::Cmd</a> to implement the <code>dancer2</code> command line
utility. This means you can introduce additional commands by just implementing
a class.</p>
<h3><a name="writing_a_new_command"></a>Writing a new command</h3>
<pre class="prettyprint">package Dancer2::CLI::Command::activate
use strict;
use warnings;
use Path::Tiny qw< path >;
use App::Cmd::Setup -command;
sub description { 'Activating our application' }
sub opt_desc {
return (
[ 'directory|d', 'Application directory' ],
# More options...
);
}
sub validate_args {
my ( $self, $opt, $args ) = @_;
$opts->{'directory'}
or $self->usage_error('You did not provide a directory');
path( $opt->{'directory'} )->is_dir
or $self->usage_error('Path provided is not a directory');
}
sub execute {
my ( $self, $opt, $args ) = @_;
my $dir = $opts->{'directory'};
# Implement the application activation
# (Whatever that means...)
}
1;</pre>
<p>In this example, we introduce a new command to <code>dancer2</code>. As long as
this class is available in your path (such as via your <code>$PERL5LIB</code>
environment variable), you will be able to run the following:</p>
<pre class="prettyprint">$ dancer2 activate --directory foo/</pre>
<p>(The implementation of what "activation" means in this context is left
to the reader.)</p>
<p>But what if you want to provide an alteration of an existing command -
the generation of the Dancer2 application?</p>
<h3><a name="writing_a_new_command"></a>Writing a new command</h3>
<p>Let's say you have a set of adjustments you keep doing to your
[company's] Dancer2 applications and you want to make these a default.</p>
<p>You can write it as a new command or you can subclass the existing
command and do whatever alterations you want before, during, and after
the generation of the skeleton.</p>
<pre class="prettyprint">package Dancer2::CLI::Command::mygen;
use strict;
use warnings;
use Cwd (); # Our own dependencies
# Subclass the existing "gen" command
use parent 'Dancer2::CLI::Command::gen';
sub execute {
my ( $self, $opt, $args ) = @_;
# Do whatever you want in this area, before we generate
# For example, let's make sure the application
# matches a certain naming convention
my $app_name = $opt->{'application'};
$app_name =~ /^My::Company::App::/
or $self->usage_error('App must be prefixed by "My::Company::App");
# Maybe check we are only scaffolding in a particular directory
cwd() eq '/opt/my_company/webapps/'
or $self->usage_error('Only create apps in our webapps directory');
# At this point, we can run the original scaffolding
$self->SUPER::execute( $opt, $args );
( run in 0.892 second using v1.01-cache-2.11-cpan-39bf76dae61 )