@@ -1,5 +1,39 @@
# This file documents the revision history for Perl extension Catalyst.
+5.90005 - 2011-10-22 13:35:00
+
+ New features:
+
+ - $c->uri_for_action can now take an array of CaptureArgs and Args
+ If you have an action which has both, then you can now say:
+ $c->uri_for_action('/myaction', [@captures, @args]);
+ whereas before you had to say:
+ $c->uri_for_action('/myaction', [@captures], @args);
+ The previous form is still supported, however in many cases it is
+ easier for the application code to not have to differentiate between
+ the two.
+
+ - Catalyst::ScriptRunner has been enhanced so that it will now
+ load and apply traits, making it easier to customise.
+ - MyApp::TraitFor::Script (if it exists) will be applied to all
+ scripts in the application.
+ - MyApp::TraitFor::Script::XXXX will be applied to the relevant script
+ (for example MyApp::TraitFor::Script::Server will be applied to
+ MyApp::Script::Server if it exists, or Catalyst::Script::Server
+ otherwise).
+
+ Documentation:
+
+ - Document how to get the vhost of the request in $c->req->hostname
+ to avoid confusion
+ - Remove documentation showing Global / Regex / Private actionsi
+ as whilst these still exist (and work), they are not recommended.
+ - Remove references to the -Engine flag.
+ - Remove references to the deprecated Catalyst->plugin method
+ - Spelling fixed (and tested) throughout the documentation
+ - Note that wrapping the setup method will not work with method modifiers
+ and provide an alternative.
+
5.90004 - 2011-10-11 17:12:00
Bug fixes:
@@ -184,6 +184,7 @@ t/author/http-server.t
t/author/notabs.t
t/author/pod.t
t/author/podcoverage.t
+t/author/spelling.t
t/catalyst_130pix.gif
t/conf/extra.conf.in
t/custom_exception_class_simple.t
@@ -217,6 +218,9 @@ t/lib/PluginTestApp/Controller/Root.pm
t/lib/ScriptTestApp/Script/Bar.pm
t/lib/ScriptTestApp/Script/CompileTest.pm
t/lib/ScriptTestApp/Script/Foo.pm
+t/lib/ScriptTestApp/TraitFor/Script.pm
+t/lib/ScriptTestApp/TraitFor/Script/Bar.pm
+t/lib/ScriptTestApp/TraitFor/Script/Foo.pm
t/lib/TestApp.pm
t/lib/TestApp/Action/TestBefore.pm
t/lib/TestApp/Action/TestExtraArgsAction.pm
@@ -12,7 +12,7 @@ build_requires:
configure_requires:
ExtUtils::MakeMaker: 6.42
distribution_type: module
-generated_by: 'Module::Install version 1.01'
+generated_by: 'Module::Install version 1.02'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -27,6 +27,7 @@ requires:
CGI::Simple::Cookie: 1.109
Carp: 0
Class::C3::Adopt::NEXT: 0.07
+ Class::Load: 0.08
Class::MOP: 0.95
Data::Dump: 0
Data::OptList: 0
@@ -73,4 +74,4 @@ resources:
homepage: http://dev.catalyst.perl.org/
license: http://dev.perl.org/licenses/
repository: git://git.shadowcat.co.uk/catagits/Catalyst-Runtime.git
-version: 5.90004
+version: 5.90005
@@ -18,6 +18,7 @@ requires 'namespace::autoclean' => '0.09';
requires 'namespace::clean' => '0.13';
requires 'B::Hooks::EndOfScope' => '0.08';
requires 'MooseX::Emulate::Class::Accessor::Fast' => '0.00903';
+requires 'Class::Load' => '0.08';
requires 'Class::MOP' => '0.95';
requires 'Data::OptList';
requires 'Moose' => '1.03';
@@ -88,6 +89,7 @@ author_requires(map {; $_ => 0 } qw(
Test::NoTabs
Test::Pod
Test::Pod::Coverage
+ Test::Spelling
Pod::Coverage::TrustPod
));
@@ -17,11 +17,14 @@ my %FeatureMap = (
);
# various lexical flags
-my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $HasCPANPLUS );
+my ( @Missing, @Existing, %DisabledTests, $UnderCPAN, $InstallDepsTarget, $HasCPANPLUS );
my (
- $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps
+ $Config, $CheckOnly, $SkipInstall, $AcceptDefault, $TestOnly, $AllDeps,
+ $UpgradeDeps
);
-my ( $PostambleActions, $PostambleUsed );
+my ( $PostambleActions, $PostambleActionsNoTest, $PostambleActionsUpgradeDeps,
+ $PostambleActionsUpgradeDepsNoTest, $PostambleActionsListDeps,
+ $PostambleActionsListAllDeps, $PostambleUsed, $NoTest);
# See if it's a testing or non-interactive session
_accept_default( $ENV{AUTOMATED_TESTING} or ! -t STDIN );
@@ -31,6 +34,10 @@ sub _accept_default {
$AcceptDefault = shift;
}
+sub _installdeps_target {
+ $InstallDepsTarget = shift;
+}
+
sub missing_modules {
return @Missing;
}
@@ -63,6 +70,11 @@ sub _init {
__PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
exit 0;
}
+ elsif ( $arg =~ /^--upgradedeps=(.*)$/ ) {
+ $UpgradeDeps = 1;
+ __PACKAGE__->install( $Config, @Missing = split( /,/, $1 ) );
+ exit 0;
+ }
elsif ( $arg =~ /^--default(?:deps)?$/ ) {
$AcceptDefault = 1;
}
@@ -125,7 +137,7 @@ sub import {
# check entirely since we don't want to have to load (and configure)
# an old CPAN just for a cosmetic message
- $UnderCPAN = _check_lock(1) unless $SkipInstall;
+ $UnderCPAN = _check_lock(1) unless $SkipInstall || $InstallDepsTarget;
while ( my ( $feature, $modules ) = splice( @args, 0, 2 ) ) {
my ( @required, @tests, @skiptests );
@@ -207,6 +219,7 @@ sub import {
$CheckOnly
or ($mandatory and $UnderCPAN)
or $AllDeps
+ or $InstallDepsTarget
or _prompt(
qq{==> Auto-install the }
. ( @required / 2 )
@@ -237,10 +250,17 @@ sub import {
}
}
- if ( @Missing and not( $CheckOnly or $UnderCPAN ) ) {
+ if ( @Missing and not( $CheckOnly or $UnderCPAN) ) {
require Config;
- print
-"*** Dependencies will be installed the next time you type '$Config::Config{make}'.\n";
+ my $make = $Config::Config{make};
+ if ($InstallDepsTarget) {
+ print
+"*** To install dependencies type '$make installdeps' or '$make installdeps_notest'.\n";
+ }
+ else {
+ print
+"*** Dependencies will be installed the next time you type '$make'.\n";
+ }
# make an educated guess of whether we'll need root permission.
print " (You may need to do that as the 'root' user.)\n"
@@ -271,6 +291,10 @@ END_MESSAGE
sub _check_lock {
return unless @Missing or @_;
+ if ($ENV{PERL5_CPANM_IS_RUNNING}) {
+ return _running_under('cpanminus');
+ }
+
my $cpan_env = $ENV{PERL5_CPAN_IS_RUNNING};
if ($ENV{PERL5_CPANPLUS_IS_RUNNING}) {
@@ -332,6 +356,11 @@ sub install {
}
}
+ if ($UpgradeDeps) {
+ push @modules, @installed;
+ @installed = ();
+ }
+
return @installed unless @modules; # nothing to do
return @installed if _check_lock(); # defer to the CPAN shell
@@ -463,6 +492,11 @@ sub _cpanplus_config {
} else {
die "*** Cannot convert option $key = '$value' to CPANPLUS version.\n";
}
+ push @config, 'prereqs', $value;
+ } elsif ( $key eq 'force' ) {
+ push @config, $key, $value;
+ } elsif ( $key eq 'notest' ) {
+ push @config, 'skiptest', $value;
} else {
die "*** Cannot convert option $key to CPANPLUS version.\n";
}
@@ -497,10 +531,14 @@ sub _install_cpan {
# set additional options
while ( my ( $opt, $arg ) = splice( @config, 0, 2 ) ) {
( $args{$opt} = $arg, next )
- if $opt =~ /^force$/; # pseudo-option
+ if $opt =~ /^(?:force|notest)$/; # pseudo-option
$CPAN::Config->{$opt} = $arg;
}
+ if ($args{notest} && (not CPAN::Shell->can('notest'))) {
+ die "Your version of CPAN is too old to support the 'notest' pragma";
+ }
+
local $CPAN::Config->{prerequisites_policy} = 'follow';
while ( my ( $pkg, $ver ) = splice( @modules, 0, 2 ) ) {
@@ -519,8 +557,16 @@ sub _install_cpan {
delete $INC{$inc};
}
- my $rv = $args{force} ? CPAN::Shell->force( install => $pkg )
- : CPAN::Shell->install($pkg);
+ my $rv = do {
+ if ($args{force}) {
+ CPAN::Shell->force( install => $pkg )
+ } elsif ($args{notest}) {
+ CPAN::Shell->notest( install => $pkg )
+ } else {
+ CPAN::Shell->install($pkg)
+ }
+ };
+
$rv ||= eval {
$CPAN::META->instance( 'CPAN::Distribution', $obj->cpan_file, )
->{install}
@@ -763,6 +809,35 @@ sub _make_args {
: "\$(NOECHO) \$(NOOP)"
);
+ my $deps_list = join( ',', @Missing, @Existing );
+
+ $PostambleActionsUpgradeDeps =
+ "\$(PERL) $0 --config=$config --upgradedeps=$deps_list";
+
+ my $config_notest =
+ join( ',', (UNIVERSAL::isa( $Config, 'HASH' ) ? %{$Config} : @{$Config}),
+ 'notest', 1 )
+ if $Config;
+
+ $PostambleActionsNoTest = (
+ ($missing and not $UnderCPAN)
+ ? "\$(PERL) $0 --config=$config_notest --installdeps=$missing"
+ : "\$(NOECHO) \$(NOOP)"
+ );
+
+ $PostambleActionsUpgradeDepsNoTest =
+ "\$(PERL) $0 --config=$config_notest --upgradedeps=$deps_list";
+
+ $PostambleActionsListDeps =
+ '@$(PERL) -le "print for @ARGV" '
+ . join(' ', map $Missing[$_], grep $_ % 2 == 0, 0..$#Missing);
+
+ my @all = (@Missing, @Existing);
+
+ $PostambleActionsListAllDeps =
+ '@$(PERL) -le "print for @ARGV" '
+ . join(' ', map $all[$_], grep $_ % 2 == 0, 0..$#all);
+
return %args;
}
@@ -797,11 +872,15 @@ sub Write {
sub postamble {
$PostambleUsed = 1;
+ my $fragment;
- return <<"END_MAKE";
+ $fragment .= <<"AUTO_INSTALL" if !$InstallDepsTarget;
config :: installdeps
\t\$(NOECHO) \$(NOOP)
+AUTO_INSTALL
+
+ $fragment .= <<"END_MAKE";
checkdeps ::
\t\$(PERL) $0 --checkdeps
@@ -809,12 +888,28 @@ checkdeps ::
installdeps ::
\t$PostambleActions
+installdeps_notest ::
+\t$PostambleActionsNoTest
+
+upgradedeps ::
+\t$PostambleActionsUpgradeDeps
+
+upgradedeps_notest ::
+\t$PostambleActionsUpgradeDepsNoTest
+
+listdeps ::
+\t$PostambleActionsListDeps
+
+listalldeps ::
+\t$PostambleActionsListAllDeps
+
END_MAKE
+ return $fragment;
}
1;
__END__
-#line 1071
+#line 1178
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -73,6 +73,17 @@ sub auto_install {
);
}
+sub installdeps_target {
+ my ($self, @args) = @_;
+
+ $self->include('Module::AutoInstall');
+ require Module::AutoInstall;
+
+ Module::AutoInstall::_installdeps_target(1);
+
+ $self->auto_install(@args);
+}
+
sub auto_install_now {
my $self = shift;
$self->auto_install(@_);
@@ -4,7 +4,7 @@ package Module::Install::Base;
use strict 'vars';
use vars qw{$VERSION};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
}
# Suspend handler for "redefined" warnings
@@ -9,7 +9,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -8,7 +8,7 @@ use Fcntl qw/:flock :seek/;
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -170,7 +170,7 @@ sub perl_version {
# Normalize the version
$version = $self->_perl_version($version);
- # We don't support the reall old versions
+ # We don't support the really old versions
unless ( $version >= 5.005 ) {
die "Module::Install only supports 5.005 or newer (use ExtUtils::MakeMaker)\n";
}
@@ -582,7 +582,7 @@ sub bugtracker_from {
sub requires_from {
my $self = shift;
my $content = Module::Install::_readperl($_[0]);
- my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+([\d\.]+)/mg;
+ my @requires = $content =~ m/^use\s+([^\W\d]\w*(?:::\w+)*)\s+(v?[\d\.]+)/mg;
while ( @requires ) {
my $module = shift @requires;
my $version = shift @requires;
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = 'Module::Install::Base';
$ISCORE = 1;
}
@@ -6,7 +6,7 @@ use Module::Install::Base ();
use vars qw{$VERSION @ISA $ISCORE};
BEGIN {
- $VERSION = '1.01';
+ $VERSION = '1.02';
@ISA = qw{Module::Install::Base};
$ISCORE = 1;
}
@@ -31,7 +31,7 @@ BEGIN {
# This is not enforced yet, but will be some time in the next few
# releases once we can make sure it won't clash with custom
# Module::Install extensions.
- $VERSION = '1.01';
+ $VERSION = '1.02';
# Storage for the pseudo-singleton
$MAIN = undef;
@@ -88,6 +88,19 @@ sub compare {
return $a1_args <=> $a2_args;
}
+sub number_of_args {
+ my ( $self ) = @_;
+ return 0 unless exists $self->attributes->{Args};
+ return $self->attributes->{Args}[0];
+}
+
+sub number_of_captures {
+ my ( $self ) = @_;
+
+ return 0 unless exists $self->attributes->{CaptureArgs};
+ return $self->attributes->{CaptureArgs}[0] || 0;
+}
+
__PACKAGE__->meta->make_immutable;
1;
@@ -147,6 +160,14 @@ C<private_path> of an action is always suitable for passing to C<forward>.
Returns the sub name of this action.
+=head2 number_of_args
+
+Returns the number of args this action expects. This is 0 if the action doesn't take any arguments and undef if it will take any number of arguments.
+
+=head2 number_of_captures
+
+Returns the number of captures this action expects for L<Chained|Catalyst::DispatchType::Chained> actions.
+
=head2 meta
Provided by Moose.
@@ -4,7 +4,6 @@ use Moose;
extends qw(Catalyst::Action);
has chain => (is => 'rw');
-
no Moose;
=head1 NAME
@@ -30,8 +29,8 @@ sub dispatch {
my $last = pop(@chain);
foreach my $action ( @chain ) {
my @args;
- if (my $cap = $action->attributes->{CaptureArgs}) {
- @args = splice(@captures, 0, $cap->[0]);
+ if (my $cap = $action->number_of_captures) {
+ @args = splice(@captures, 0, $cap);
}
local $c->request->{arguments} = \@args;
$action->dispatch( $c );
@@ -45,6 +44,15 @@ sub from_chain {
return $self->new({ %$final, chain => $actions });
}
+sub number_of_captures {
+ my ( $self ) = @_;
+ my $chain = $self->chain;
+ my $captures = 0;
+
+ $captures += $_->number_of_captures for @$chain;
+ return $captures;
+}
+
__PACKAGE__->meta->make_immutable;
1;
@@ -67,6 +75,10 @@ actions in order.
Takes a list of Catalyst::Action objects and constructs and returns a
Catalyst::ActionChain object representing a chain of these actions
+=head2 number_of_captures
+
+Returns the total number of captures for the entire chain of actions.
+
=head2 meta
Provided by Moose
@@ -81,8 +81,12 @@ L<Class::Accessor::Grouped>;
=head1 AUTHOR
+=begin stopwords
+
Guillermo Roditi
+=end stopwords
+
=head1 COPYRIGHT
This library is free software. You can redistribute it and/or modify it under
@@ -63,10 +63,14 @@ L<Catalyst::Controller>
L<CatalystX::LeakChecker>
+=begin stopwords
+
=head1 AUTHOR
Florian Ragwitz E<lt>rafl@debian.orgE<gt>
+=end stopwords
+
=head1 COPYRIGHT
This library is free software. You can redistribute it and/or modify it under
@@ -53,7 +53,7 @@ Catalyst::Component - Catalyst Component Base Class
This is the universal base class for Catalyst components
(Model/View/Controller).
-It provides you with a generic new() for instantiation through Catalyst's
+It provides you with a generic new() for component construction through Catalyst's
component loader with config() support and a process() method placeholder.
=cut
@@ -180,7 +180,7 @@ The arguments are expected to be a hashref and are merged with the
C<< __PACKAGE__->config >> hashref before calling C<< ->new >>
to instantiate the component.
-You can override it in your components to do custom instantiation, using
+You can override it in your components to do custom construction, using
something like this:
sub COMPONENT {
@@ -482,7 +482,7 @@ Sets 'path_prefix', as described below.
Allows you to set the attributes that the dispatcher creates actions out of.
This allows you to do 'rails style routes', or override some of the
-attribute defintions of actions composed from Roles.
+attribute definitions of actions composed from Roles.
You can set arguments globally (for all actions of the controller) and
specifically (for a single action).
@@ -588,8 +588,8 @@ sub _find_or_create_namespace_node {
=head2 $self->setup_actions( $class, $context )
-Loads all of the preload dispatch types, registers their actions and then
-loads all of the postload dispatch types, and iterates over the tree of
+Loads all of the pre-load dispatch types, registers their actions and then
+loads all of the post-load dispatch types, and iterates over the tree of
actions, displaying the debug information if appropriate.
=cut
@@ -45,6 +45,8 @@ sub _build_basename {
no Moose;
+=for stopwords uploadtmp
+
=head1 NAME
Catalyst::Request::Upload - handles file upload requests
@@ -129,9 +131,9 @@ Returns the size of the uploaded file in bytes.
Returns a scalar containing the contents of the temporary file.
-Note that this method will cause the filehandle pointed to by
-C<< $upload->fh >> to be seeked to the start of the file,
-and the file handle to be put into binary mode.
+Note that this will cause the filehandle pointed to by C<< $upload->fh >> to
+be reset to the start of the file using seek and the file handle to be put
+into binary mode.
=cut
@@ -138,6 +138,8 @@ sub query_params { shift->query_parameters(@_) }
sub path_info { shift->path(@_) }
sub snippets { shift->captures(@_) }
+=for stopwords param params
+
=head1 NAME
Catalyst::Request - provides information about the current client request
@@ -228,7 +230,7 @@ Shortcut for L</arguments>.
=head2 $req->base
Contains the URI base. This will always have a trailing slash. Note that the
-URI scheme (eg., http vs. https) must be determined through heuristics;
+URI scheme (e.g., http vs. https) must be determined through heuristics;
depending on your server configuration, it may be incorrect. See $req->secure
for more info.
@@ -316,7 +318,7 @@ Returns an L<HTTP::Headers> object containing the headers for the current reques
=head2 $req->hostname
-Returns the hostname of the client.
+Returns the hostname of the client. Use C<< $req->uri->host >> to get the hostname of the server.
=head2 $req->input
@@ -487,7 +489,7 @@ Shortcut for $req->headers->referer. Returns the referring page.
=head2 $req->secure
Returns true or false, indicating whether the connection is secure
-(https). Note that the URI scheme (eg., http vs. https) must be determined
+(https). Note that the URI scheme (e.g., http vs. https) must be determined
through heuristics, and therefore the reliability of $req->secure will depend
on your server configuration. If you are serving secure pages on the standard
SSL port (443) and/or setting the HTTPS environment variable, $req->secure
@@ -7,7 +7,7 @@ BEGIN { require 5.008004; }
# Remember to update this in Catalyst as well!
-our $VERSION = '5.90004';
+our $VERSION = '5.90005';
=head1 NAME
@@ -23,6 +23,10 @@ Catalyst::Script::CGI - The CGI Catalyst Script
This is a script to run the Catalyst engine specialized for the CGI environment.
+=head1 SEE ALSO
+
+L<Catalyst::ScriptRunner>
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -90,6 +90,10 @@ Existing component files are not overwritten. If any of the component files
to be created already exist the file will be written with a '.new' suffix.
This behavior can be suppressed with the C<--force> option.
+=head1 SEE ALSO
+
+L<Catalyst::ScriptRunner>
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -153,6 +153,10 @@ Catalyst::Script::FastCGI - The FastCGI Catalyst Script
Run a Catalyst application as fastcgi.
+=head1 SEE ALSO
+
+L<Catalyst::ScriptRunner>
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -322,6 +322,10 @@ Catalyst::Script::Server - Catalyst test server
Run a Catalyst test server for this application.
+=head1 SEE ALSO
+
+L<Catalyst::ScriptRunner>
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -33,6 +33,10 @@ Catalyst::Script::Test - Test Catalyst application on the command line
Script to perform a test hit against your application and display the output.
+=head1 SEE ALSO
+
+L<Catalyst::ScriptRunner>
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -3,21 +3,48 @@ use Moose;
use FindBin;
use lib;
use File::Spec;
-use namespace::autoclean;
+use Class::Load qw/ load_first_existing_class load_optional_class /;
+use namespace::autoclean -also => 'subclass_with_traits';
+use Try::Tiny;
+
+sub find_script_class {
+ my ($self, $app, $script) = @_;
+ return load_first_existing_class("${app}::Script::${script}", "Catalyst::Script::$script");
+}
+
+sub find_script_traits {
+ my ($self, @try) = @_;
+
+ return grep { load_optional_class($_) } @try;
+}
+
+sub subclass_with_traits {
+ my ($base, @traits) = @_;
+
+ my $meta = Class::MOP::class_of($base)->create_anon_class(
+ superclasses => [ $base ],
+ roles => [ @traits ],
+ cache => 1,
+ );
+ $meta->add_method(meta => sub { $meta });
+
+ return $meta->name;
+}
sub run {
- my ($self, $class, $scriptclass, %args) = @_;
- my $classtoload = "${class}::Script::$scriptclass";
+ my ($self, $appclass, $scriptclass) = @_;
lib->import(File::Spec->catdir($FindBin::Bin, '..', 'lib'));
- unless ( eval { Class::MOP::load_class($classtoload) } ) {
- warn("Could not load $classtoload - falling back to Catalyst::Script::$scriptclass : $@\n")
- if $@ !~ /Can't locate/;
- $classtoload = "Catalyst::Script::$scriptclass";
- Class::MOP::load_class($classtoload);
- }
- $classtoload->new_with_options( application_name => $class, %args )->run;
+ my $class = $self->find_script_class($appclass, $scriptclass);
+
+ my @possible_traits = ("${appclass}::TraitFor::Script::${scriptclass}", "${appclass}::TraitFor::Script");
+ my @traits = $self->find_script_traits(@possible_traits);
+
+ $class = subclass_with_traits($class, @traits)
+ if @traits;
+
+ $class->new_with_options( application_name => $appclass )->run;
}
__PACKAGE__->meta->make_immutable;
@@ -34,16 +61,41 @@ Catalyst::ScriptRunner - The Catalyst Framework script runner
=head1 DESCRIPTION
-This class is responsible for running scripts, either in the application specific namespace
-(e.g. C<MyApp::Script::Server>), or the Catalyst namespace (e.g. C<Catalyst::Script::Server>)
+This class is responsible for loading and running scripts, either in the
+application specific namespace
+(e.g. C<MyApp::Script::Server>), or the Catalyst namespace (e.g. C<Catalyst::Script::Server>).
+
+If your application contains a custom script, then it will be used in preference to the generic
+script, and is expected to sub-class the standard script.
+
+=head1 TRAIT LOADING
+
+Catalyst will automatically load and apply roles to the scripts in your
+application.
+
+C<MyApp::TraitFor::Script> will be loaded if present, and will be applied to B<ALL>
+scripts.
+
+C<MyApp::TraitFor::Script::XXXX> will be loaded (if present) and for script
+individually.
=head1 METHODS
=head2 run ($application_class, $scriptclass)
-Called with two parameters, the application classs (e.g. MyApp)
+Called with two parameters, the application class (e.g. MyApp)
and the script class, (i.e. one of Server/FastCGI/CGI/Create/Test)
+=head2 find_script_class ($appname, $script_name)
+
+Finds and loads the class for the script, trying the application specific
+script first, and falling back to the generic script. Returns the script
+which was loaded.
+
+=head2 find_script_traits ($appname, @try)
+
+Finds and loads a set of traits. Returns the list of traits which were loaded.
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
@@ -166,6 +166,8 @@ __PACKAGE__->meta->make_immutable();
__END__
+=for stopwords addChild getNodeValue mysub rollup setNodeValue
+
=head1 NAME
Catalyst::Stats - Catalyst Timing Statistics Class
@@ -209,8 +209,8 @@ functions take either a URI or an L<HTTP::Request> object.
=head1 INLINE TESTS WILL NO LONGER WORK
-While it used to be possible to inline a whole testapp into a C<.t> file for a
-distribution, this will no longer work.
+While it used to be possible to inline a whole test app into a C<.t> file for
+a distribution, this will no longer work.
The convention is to place your L<Catalyst> test apps into C<t/lib> in your
distribution. E.g.: C<t/lib/TestApp.pm>, C<t/lib/TestApp/Controller/Root.pm>,
@@ -65,7 +65,7 @@ script is upgraded to use L<Catalyst::Script::HTTP>.
If you were using L<Catalyst::Engine::CGI> there is no upgrade needed if your
myapp_cgi.pl script is already upgraded to use L<Catalyst::Script::CGI>.
-=head2 Upgrading the Preforking Engine
+=head2 Upgrading Catalyst::Engine::HTTP::Prefork
If you were using L<Catalyst::Engine::HTTP::Prefork> then L<Starman>
is automatically loaded. You should (at least) change your C<Makefile.PL>
@@ -223,7 +223,7 @@ been made which could cause incompatibilities. If your application or plugin
is using deprecated code, or relying on side effects, then you could have
issues upgrading to this release.
-Most issues found with pre-existing components have been easy to
+Most issues found with existing components have been easy to
solve. This document provides a complete description of behavior changes
which may cause compatibility issues, and of new Catalyst warnings which
might be unclear.
@@ -281,7 +281,7 @@ replaces L<NEXT> with L<Class::C3::Adopt::NEXT>, forcing all components
to resolve methods using C3, rather than the unpredictable dispatch
order of L<NEXT>.
-This issue is characterised by your application failing to start due to an
+This issue manifests itself by your application failing to start due to an
error message about having a non-linear @ISA.
The Catalyst plugin most often causing this is
@@ -488,7 +488,7 @@ The following test demonstrates the problem:
use Test::More;
isnt(BaseClass->can('foo'), Child->can('foo'));
-=head2 Extending Catalyst::Request or other classes in an ad-hoc manner using mk_accessors
+=head2 Extending Catalyst::Request or other classes in an ad hoc manner using mk_accessors
Previously, it was possible to add additional accessors to Catalyst::Request
(or other classes) by calling the mk_accessors class method.
@@ -84,7 +84,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90004';
+our $VERSION = '5.90005';
sub import {
my ( $class, @arguments ) = @_;
@@ -148,7 +148,7 @@ documentation and tutorials.
use Catalyst qw/-Debug/; # include plugins here as well
### In lib/MyApp/Controller/Root.pm (autocreated)
- sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
+ sub foo : Chained('/') Args() { # called for /foo, /foo/1, /foo/1/2, etc.
my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
$c->stash->{template} = 'foo.tt'; # set the template
# lookup something from db -- stash vars are passed to TT
@@ -166,50 +166,16 @@ documentation and tutorials.
[% END %]
# called for /bar/of/soap, /bar/of/soap/10, etc.
- sub bar : Path('/bar/of/soap') { ... }
-
- # called for all actions, from the top-most controller downwards
- sub auto : Private {
- my ( $self, $c ) = @_;
- if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
- $c->res->redirect( '/login' ); # require login
- return 0; # abort request and go immediately to end()
- }
- return 1; # success; carry on to next action
- }
+ sub bar : Chained('/') PathPart('/bar/of/soap') Args() { ... }
# called after all actions are finished
- sub end : Private {
+ sub end : Action {
my ( $self, $c ) = @_;
if ( scalar @{ $c->error } ) { ... } # handle errors
return if $c->res->body; # already have a response
$c->forward( 'MyApp::View::TT' ); # render template
}
- ### in MyApp/Controller/Foo.pm
- # called for /foo/bar
- sub bar : Local { ... }
-
- # called for /blargle
- sub blargle : Global { ... }
-
- # an index action matches /foo, but not /foo/1, etc.
- sub index : Private { ... }
-
- ### in MyApp/Controller/Foo/Bar.pm
- # called for /foo/bar/baz
- sub baz : Local { ... }
-
- # first Root auto is called, then Foo auto, then this
- sub auto : Private { ... }
-
- # powerful regular expression paths are also possible
- sub details : Regex('^product/(\w+)/details$') {
- my ( $self, $c ) = @_;
- # extract the (\w+) from the URI
- my $product = $c->req->captures->[0];
- }
-
See L<Catalyst::Manual::Intro> for additional information.
=head1 DESCRIPTION
@@ -236,7 +202,7 @@ fully qualify the name by using a unary plus:
+Fully::Qualified::Plugin::Name
/;
-Special flags like C<-Debug> and C<-Engine> can also be specified as
+Special flags like C<-Debug> can also be specified as
arguments when Catalyst is loaded:
use Catalyst qw/-Debug My::Module/;
@@ -256,13 +222,6 @@ priority.
This sets the log level to 'debug' and enables full debug output on the
error screen. If you only want the latter, see L<< $c->debug >>.
-=head2 -Engine
-
-Forces Catalyst to use a specific engine. Omit the
-C<Catalyst::Engine::> prefix of the engine name, i.e.:
-
- use Catalyst qw/-Engine=CGI/;
-
=head2 -Home
Forces Catalyst to use a specific home directory, e.g.:
@@ -276,11 +235,11 @@ the name will be replaced with underscores, e.g. MyApp::Web should use
MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
If none of these are set, Catalyst will attempt to automatically detect the
-home directory. If you are working in a development envirnoment, Catalyst
+home directory. If you are working in a development environment, Catalyst
will try and find the directory containing either Makefile.PL, Build.PL or
dist.ini. If the application has been installed into the system (i.e.
you have done C<make install>), then Catalyst will use the path to your
-application module, without the .pm extension (ie, /foo/MyApp if your
+application module, without the .pm extension (e.g., /foo/MyApp if your
application was installed at /foo/MyApp.pm)
=head2 -Log
@@ -348,9 +307,10 @@ call to forward.
Note that L<< forward|/"$c->forward( $action [, \@arguments ] )" >> implies
an C<< eval { } >> around the call (actually
-L<< execute|/"$c->execute( $class, $coderef )" >> does), thus de-fatalizing
-all 'dies' within the called action. If you want C<die> to propagate you
-need to do something like:
+L<< execute|/"$c->execute( $class, $coderef )" >> does), thus rendering all
+exceptions thrown by the called action non-fatal and pushing them onto
+$c->error instead. If you want C<die> to propagate you need to do something
+like:
$c->forward('foo');
die join "\n", @{ $c->error } if @{ $c->error };
@@ -412,7 +372,7 @@ L<reverse|Catalyst::Action/reverse> return information for the visited action
when they are invoked within the visited action. This is different from the
behavior of L<< forward|/"$c->forward( $action [, \@arguments ] )" >>, which
continues to use the $c->action object from the caller action even when
-invoked from the callee.
+invoked from the called action.
C<< $c->stash >> is kept unchanged.
@@ -1035,26 +995,11 @@ sub path_to {
else { return Path::Class::File->new( $c->config->{home}, @path ) }
}
-=head2 $c->plugin( $name, $class, @args )
-
-Helper method for plugins. It creates a class data accessor/mutator and
-loads and instantiates the given class.
-
- MyApp->plugin( 'prototype', 'HTML::Prototype' );
-
- $c->prototype->define_javascript_functions;
-
-B<Note:> This method of adding plugins is deprecated. The ability
-to add plugins like this B<will be removed> in a Catalyst 5.81.
-Please do not use this functionality in new code.
-
-=cut
-
sub plugin {
my ( $class, $name, $plugin, @args ) = @_;
# See block comment in t/unit_core_plugin.t
- $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in Catalyst 5.81/);
+ $class->log->warn(qq/Adding plugin using the ->plugin method is deprecated, and will be removed in a future release/);
$class->_register_plugin( $plugin, 1 );
@@ -1083,6 +1028,9 @@ Catalyst> line.
MyApp->setup;
MyApp->setup( qw/-Debug/ );
+B<Note:> You B<should not> wrap this method with method modifiers
+or bad things will happen - wrap the C<setup_finalize> method instead.
+
=cut
sub setup {
@@ -1347,7 +1295,15 @@ sub uri_for {
}
my $action = $path;
- $path = $c->dispatcher->uri_for_action($action, $captures);
+ # ->uri_for( $action, \@captures_and_args, \%query_values? )
+ if( !@args && $action->number_of_args ) {
+ my $expanded_action = $c->dispatcher->expand_action( $action );
+
+ my $num_captures = $expanded_action->number_of_captures;
+ unshift @args, splice @$captures, $num_captures;
+ }
+
+ $path = $c->dispatcher->uri_for_action($action, $captures);
if (not defined $path) {
$c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
if $c->debug;
@@ -1398,9 +1354,9 @@ sub uri_for {
$res;
}
-=head2 $c->uri_for_action( $path, \@captures?, @args?, \%query_values? )
+=head2 $c->uri_for_action( $path, \@captures_and_args?, @args?, \%query_values? )
-=head2 $c->uri_for_action( $action, \@captures?, @args?, \%query_values? )
+=head2 $c->uri_for_action( $action, \@captures_and_args?, @args?, \%query_values? )
=over
@@ -1429,6 +1385,30 @@ You can use:
and it will create the URI /users/the-list.
+=item \@captures_and_args?
+
+Optional array reference of Captures (i.e. C<<CaptureArgs or $c->req->captures>)
+and arguments to the request. Usually used with L<Catalyst::DispatchType::Chained>
+to interpolate all the parameters in the URI.
+
+=item @args?
+
+Optional list of extra arguments - can be supplied in the C<< \@captures_and_args? >>
+array ref, or here - whichever is easier for your code..
+
+If your action may have a zero, a fixed or a variable number of args (e.g. C<< Args(1) >>
+for a fixed number or C<< Args() >> for a variable number)..
+
+=item \%query_values?
+
+Optional array reference of query parameters to append. E.g.
+
+ { foo => 'bar' }
+
+will generate
+
+ /rest/of/your/uri?foo=bar
+
=back
=cut
@@ -2258,7 +2238,7 @@ sub log_response_status_line {
=head2 $c->log_response_headers($headers);
-Hook method which can be wrapped by plugins to log the responseheaders.
+Hook method which can be wrapped by plugins to log the response headers.
No-op in the default implementation.
=cut
@@ -2868,7 +2848,7 @@ sub setup_stats {
=head2 $c->registered_plugins
Returns a sorted list of the plugins which have either been stated in the
-import list or which have been added via C<< MyApp->plugin(@args); >>.
+import list.
If passed a given plugin name, it will report a boolean value indicating
whether or not that plugin is loaded. A fully qualified name is required if
@@ -3039,7 +3019,7 @@ welcome screens
C<parse_on_demand> - The request body (for example file uploads) will not be parsed
until it is accessed. This allows you to (for example) check authentication (and reject
-the upload) before actually recieving all the data. See L</ON-DEMAND PARSER>
+the upload) before actually receiving all the data. See L</ON-DEMAND PARSER>
=item *
@@ -3060,7 +3040,7 @@ to be shown in hit debug tables in the test server.
=item *
-C<use_request_uri_for_path> - Controlls if the C<REQUEST_URI> or C<PATH_INFO> environment
+C<use_request_uri_for_path> - Controls if the C<REQUEST_URI> or C<PATH_INFO> environment
variable should be used for determining the request path.
Most web server environments pass the requested path to the application using environment variables,
@@ -3075,7 +3055,7 @@ is determined by the C<< $c->config(use_request_uri_for_path) >> setting (which
=item use_request_uri_for_path => 0
This is the default (and the) traditional method that Catalyst has used for determining the path information.
-The path is synthesised from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables.
+The path is generated from a combination of the C<PATH_INFO> and C<SCRIPT_NAME> environment variables.
The allows the application to behave correctly when C<mod_rewrite> is being used to redirect requests
into the application, as these variables are adjusted by mod_rewrite to take account for the redirect.
@@ -3215,6 +3195,8 @@ Wiki:
=head2 L<Catalyst::Test> - The test suite.
+=begin stopwords
+
=head1 PROJECT FOUNDER
sri: Sebastian Riedel <sri@cpan.org>
@@ -3357,6 +3339,8 @@ rainboxx: Matthias Dietrich, C<perl@rainboxx.de>
dd070: Dhaval Dhanani <dhaval070@gmail.com>
+=end stopwords
+
=head1 COPYRIGHT
Copyright (c) 2005, the above named PROJECT FOUNDER and CONTRIBUTORS.
@@ -2,23 +2,21 @@ use strict;
use warnings;
use Test::More;
use FindBin qw/$Bin/;
+use Test::Exception;
use lib "$Bin/../lib";
use_ok('Catalyst::ScriptRunner');
-is Catalyst::ScriptRunner->run('ScriptTestApp', 'Foo'), 'ScriptTestApp::Script::Foo',
- 'Script existing only in app';
-is Catalyst::ScriptRunner->run('ScriptTestApp', 'Bar'), 'ScriptTestApp::Script::Bar',
+is Catalyst::ScriptRunner->run('ScriptTestApp', 'Foo'), 'mooScriptTestApp::Script::Foo42',
+ 'Script existing only in app got trait applied';
+is Catalyst::ScriptRunner->run('ScriptTestApp', 'Bar'), 'mooScriptTestApp::Script::Bar23',
'Script existing in both app and Catalyst - prefers app';
-is Catalyst::ScriptRunner->run('ScriptTestApp', 'Baz'), 'Catalyst::Script::Baz',
+is Catalyst::ScriptRunner->run('ScriptTestApp', 'Baz'), 'mooCatalyst::Script::Baz',
'Script existing only in Catalyst';
# +1 test for the params passed to new_with_options in t/lib/Catalyst/Script/Baz.pm
-{
- my $warnings = '';
- local $SIG{__WARN__} = sub { $warnings .= shift };
- is 'Catalyst::Script::CompileTest', Catalyst::ScriptRunner->run('ScriptTestApp', 'CompileTest');
- like $warnings, qr/Does not compile/;
- like $warnings, qr/Could not load ScriptTestApp::Script::CompileTest - falling back to Catalyst::Script::CompileTest/;
-}
+
+throws_ok(sub {
+ Catalyst::ScriptRunner->run('ScriptTestApp', 'CompileTest');
+}, qr/Couldn't load class/);
done_testing;
@@ -8,8 +8,6 @@ use lib "$FindBin::Bin/../lib";
use Test::More;
-plan tests => 33;
-
use_ok('TestApp');
my $dispatcher = TestApp->dispatcher;
@@ -143,10 +141,18 @@ is($context->uri_for($chained_action, [ 1 ], 2, { q => 1 }),
'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4?x=5',
'uri_for_action correct for chained with multiple captures and args' );
+ is( $context->uri_for_action( '/action/chained/endpoint2', [1,2,3,4], { x => 5 } ),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4?x=5',
+ 'uri_for_action correct for chained with multiple captures and args combined' );
+
is( $context->uri_for_action( '/action/chained/three_end', [1,2,3], (4,5,6) ),
'http://127.0.0.1/foo/chained/one/1/two/2/3/three/4/5/6',
'uri_for_action correct for chained with multiple capturing actions' );
+ is( $context->uri_for_action( '/action/chained/three_end', [1,2,3,4,5,6] ),
+ 'http://127.0.0.1/foo/chained/one/1/two/2/3/three/4/5/6',
+ 'uri_for_action correct for chained with multiple capturing actions and args combined' );
+
my $action_needs_two = '/action/chained/endpoint2';
ok( ! defined( $context->uri_for_action($action_needs_two, [1], (2,3)) ),
@@ -155,7 +161,11 @@ is($context->uri_for($chained_action, [ 1 ], 2, { q => 1 }),
is( $context->uri_for_action($action_needs_two, [1,2], (2,3)),
'http://127.0.0.1/foo/chained/foo2/1/2/end2/2/3',
'uri_for_action returns correct uri for correct captures' );
-
+
+ is( $context->uri_for_action($action_needs_two, [1,2,2,3]),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2/2/3',
+ 'uri_for_action returns correct uri for correct captures and args combined' );
+
ok( ! defined( $context->uri_for_action($action_needs_two, [1,2,3], (2,3)) ),
'uri_for_action returns undef for too many captures' );
@@ -163,26 +173,49 @@ is($context->uri_for($chained_action, [ 1 ], 2, { q => 1 }),
'http://127.0.0.1/foo/chained/foo2/1/2/end2/3',
'uri_for_action returns uri with lesser args than specified on action' );
+ is( $context->uri_for_action($action_needs_two, [1,2,3]),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2/3',
+ 'uri_for_action returns uri with lesser args than specified on action with captures combined' );
+
is( $context->uri_for_action($action_needs_two, [1,2], (3,4,5)),
'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4/5',
'uri_for_action returns uri with more args than specified on action' );
+ is( $context->uri_for_action($action_needs_two, [1,2,3,4,5]),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4/5',
+ 'uri_for_action returns uri with more args than specified on action with captures combined' );
+
is( $context->uri_for_action($action_needs_two, [1,''], (3,4)),
'http://127.0.0.1/foo/chained/foo2/1//end2/3/4',
'uri_for_action returns uri with empty capture on undef capture' );
+ is( $context->uri_for_action($action_needs_two, [1,'',3,4]),
+ 'http://127.0.0.1/foo/chained/foo2/1//end2/3/4',
+ 'uri_for_action returns uri with empty capture on undef capture and args combined' );
+
is( $context->uri_for_action($action_needs_two, [1,2], ('',3)),
'http://127.0.0.1/foo/chained/foo2/1/2/end2//3',
'uri_for_action returns uri with empty arg on undef argument' );
+ is( $context->uri_for_action($action_needs_two, [1,2,'',3]),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2//3',
+ 'uri_for_action returns uri with empty arg on undef argument and args combined' );
+
is( $context->uri_for_action($action_needs_two, [1,2], (3,'')),
'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/',
'uri_for_action returns uri with empty arg on undef last argument' );
+ is( $context->uri_for_action($action_needs_two, [1,2,3,'']),
+ 'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/',
+ 'uri_for_action returns uri with empty arg on undef last argument with captures combined' );
+
my $complex_chained = '/action/chained/empty_chain_f';
is( $context->uri_for_action( $complex_chained, [23], (13), {q => 3} ),
'http://127.0.0.1/foo/chained/empty/23/13?q=3',
'uri_for_action returns correct uri for chain with many empty path parts' );
+ is( $context->uri_for_action( $complex_chained, [23,13], {q => 3} ),
+ 'http://127.0.0.1/foo/chained/empty/23/13?q=3',
+ 'uri_for_action returns correct uri for chain with many empty path parts with captures and args combined' );
eval { $context->uri_for_action( '/does/not/exist' ) };
like $@, qr{^Can't find action for path '/does/not/exist'},
@@ -190,3 +223,5 @@ is($context->uri_for($chained_action, [ 1 ], 2, { q => 1 }),
}
+done_testing;
+
@@ -9,6 +9,7 @@ my @modules = all_modules;
our @private = ( 'BUILD' );
foreach my $module (@modules) {
local @private = (@private, 'run') if $module =~ /^Catalyst::Script::/;
+ local @private = (@private, 'plugin') if $module =~ /^Catalyst$/;
pod_coverage_ok($module, {
also_private => \@private,
coverage_class => 'Pod::Coverage::TrustPod',
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+use Test::More;
+use Test::Spelling;
+
+add_stopwords(qw(
+ API CGI MVC PSGI Plack README SSI Starman XXXX URI htaccess middleware
+ mixins namespace psgi startup Deprecations catamoose cataplack linearize
+ subclasses subdirectories refactoring adaptors
+ undef env regex unary rethrow rethrows stringifies CPAN STDERR SIGCHLD baz
+ roadmap wishlist refactor refactored Runtime pluggable pluggability hoc apis
+ fastcgi nginx Lighttpd IIS middlewares backend IRC
+ ctx _application MyApp restarter httponly Utils stash's unescapes
+ dispatchtype dispatchtypes redispatch redispatching
+ CaptureArgs ChainedParent PathPart PathPrefix
+ BUILDARGS metaclass namespaces pre
+ filename tempname request's subdirectory ini uninstalled uppercased
+ wiki bitmask uri url urls dir hostname proxied http https IP SSL
+));
+set_spell_cmd('aspell list -l en');
+all_pod_files_spelling_ok();
+
+done_testing();
@@ -0,0 +1,10 @@
+package ScriptTestApp::TraitFor::Script::Bar;
+use Moose::Role;
+use namespace::autoclean;
+
+around run => sub {
+ my ($orig, $self, @args) = @_;
+ return $self->$orig(@args) . '23';
+};
+
+1;
@@ -0,0 +1,10 @@
+package ScriptTestApp::TraitFor::Script::Foo;
+use Moose::Role;
+use namespace::autoclean;
+
+around run => sub {
+ my ($orig, $self, @args) = @_;
+ return $self->$orig(@args) . '42';
+};
+
+1;
@@ -0,0 +1,10 @@
+package ScriptTestApp::TraitFor::Script;
+use Moose::Role;
+use namespace::autoclean;
+
+around run => sub {
+ my ($orig, $self, @args) = @_;
+ return 'moo' . $self->$orig(@args);
+};
+
+1;
@@ -5,7 +5,7 @@ use base qw[TestApp::View::Dump];
sub process {
my ( $self, $c ) = @_;
- return $self->SUPER::process( $c, $c->action );
+ return $self->SUPER::process( $c, $c->action, 0 );
}
1;
@@ -7,13 +7,15 @@ use Data::Dumper ();
use Scalar::Util qw(blessed weaken);
sub dump {
- my ( $self, $reference ) = @_;
+ my ( $self, $reference, $purity ) = @_;
return unless $reference;
+ $purity = defined $purity ? $purity : 1;
+
my $dumper = Data::Dumper->new( [$reference] );
$dumper->Indent(1);
- $dumper->Purity(1);
+ $dumper->Purity($purity);
$dumper->Useqq(0);
$dumper->Deepcopy(1);
$dumper->Quotekeys(0);
@@ -23,7 +25,7 @@ sub dump {
}
sub process {
- my ( $self, $c, $reference ) = @_;
+ my ( $self, $c, $reference, $purity ) = @_;
# Force processing of on-demand data
$c->prepare_body;
@@ -37,7 +39,7 @@ sub process {
my $context = delete $reference->{_context};
if ( my $output =
- $self->dump( $reference ) )
+ $self->dump( $reference, $purity ) )
{
$c->res->headers->content_type('text/plain');