- Port to Moose
- Added test for action stringify
- Added test for component instances getting $self->{value} from config.
+ - Chained doc improvements (rev 8326-8328)
5.7XXXXXX XXXX
- Fix some Win32 test failures
requires 'MRO::Compat';
if (-e 'inc/.author') {
- build_requires 'Test::Perl::Critic';
+ build_requires 'Test::NoTabs';
build_requires 'Test::Pod' => 1.14;
build_requires 'Test::Pod::Coverage' => 1.04;
sub _filter_component {
my ( $c, $comp, @args ) = @_;
- if ( eval { $comp->can('ACCEPT_CONTEXT'); } ) {
+ if ( Scalar::Util::blessed($c) && eval { $comp->can('ACCEPT_CONTEXT'); } ) {
return $comp->ACCEPT_CONTEXT( $c, @args );
}
sub uri_for_action { }
+sub expand_action { }
+
=head1 AUTHORS
Catalyst Contributors, see Catalyst.pm
}
+sub expand_action {
+ my ($self, $action) = @_;
+
+ return unless $action->attributes && $action->attributes->{Chained};
+
+ my @chain;
+ my $curr = $action;
+
+ while ($curr) {
+ push @chain, $curr;
+ my $parent = $curr->attributes->{Chained}->[0];
+ $curr = $self->_actions->{$parent};
+ }
+
+ return Catalyst::ActionChain->from_chain([reverse @chain]);
+}
+
__PACKAGE__->meta->make_immutable;
=head1 USAGE
C</foo/bar/...>. If you don't specify C<:PathPart> it has the same
effect as using C<:PathPart>, it would default to the action name.
+=item PathPrefix
+
+Sets PathPart to the path_prefix of the current controller.
+
=item Chained
Has to be specified for every child in the chain. Possible values are
-absolute and relative private action paths, with the relatives pointing
-to the current controller, or a single slash C</> to tell Catalyst that
-this is the root of a chain. The attribute C<:Chained> without arguments
-also defaults to the C</> behavior.
+absolute and relative private action paths or a single slash C</> to
+tell Catalyst that this is the root of a chain. The attribute
+C<:Chained> without arguments also defaults to the C</> behavior.
+Relative action paths may use C<../> to refer to actions in parent
+controllers.
Because you can specify an absolute path to the parent action, it
doesn't matter to Catalyst where that parent is located. So, if your
C</foo/bar>. That action chains directly to C</>, so the C</bar/*/baz/*>
chain comes out as the end product.
+=item ChainedParent
+
+Chains an action to another action with the same name in the parent
+controller. For Example:
+
+ # in MyApp::Controller::Foo
+ sub bar : Chained CaptureArgs(1) { ... }
+
+ # in MyApp::Controller::Foo::Moo
+ sub bar : ChainedParent Args(1) { ... }
+
+This builds a chain like C</bar/*/bar/*>.
+
=item CaptureArgs
Must be specified for every part of the chain that is not an
return 0;
}
+ $action = $self->expand_action($action);
+
local $c->request->{arguments} = $args;
$c->namespace($action->namespace);
$c->action($action);
return undef;
}
+sub expand_action {
+ my ($self, $action) = @_;
+
+ foreach my $dispatch_type (@{ $self->_dispatch_types }) {
+ my $expanded = $dispatch_type->expand_action($action);
+ return $expanded if $expanded;
+ }
+
+ return $action;
+}
+
=head2 $self->register( $c, $action )
Make sure all required dispatch types for this action are loaded, then
for the Catalyst framework. It's liable to change at any time. This document
lives in the the catalyst trunk, currently at
- http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst/lib/Catalyst/ROADMAP.pod
+ http://dev.catalyst.perl.org/repos/Catalyst/Catalyst-Runtime/5.80/trunk/lib/Catalyst/ROADMAP.pod
Make sure you get it from there to ensure you have the latest version.
+++ /dev/null
-include = CodeLayout::ProhibitHardTabs
-only = 1
-
-[CodeLayout::ProhibitHardTabs]
-allow_leading_tabs = 0
\ No newline at end of file
plan skip_all => 'Critic test only for developers.';
}
else {
- eval { require Test::Perl::Critic };
+ eval { require Test::NoTabs };
if ( $@ ) {
plan tests => 1;
- fail( 'You must install Test::Perl::Critic to run 04critic.t' );
+ fail( 'You must install Test::NoTabs to run 04critic.t' );
exit;
}
}
-my $rcfile = File::Spec->catfile( 't', '04critic.rc' );
-Test::Perl::Critic->import( -profile => $rcfile );
-all_critic_ok();
\ No newline at end of file
+Test::NoTabs->import;
+all_perl_files_ok(qw/lib/);
{
my $args;
- no warnings;
- *MyApp::M::Model::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
+ {
+ no warnings 'once';
+ *MyApp::M::Model::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
+ }
+
+ my $c = bless {}, 'MyApp';
- MyApp->component('MyApp::M::Model', qw/foo bar/);
+ $c->component('MyApp::M::Model', qw/foo bar/);
is_deeply($args, [qw/foo bar/], 'args passed to ACCEPT_CONTEXT ok');
- MyApp->component('M::Model', qw/foo2 bar2/);
+ $c->component('M::Model', qw/foo2 bar2/);
is_deeply($args, [qw/foo2 bar2/], 'args passed to ACCEPT_CONTEXT ok');
- MyApp->component('Mode', qw/foo3 bar3/);
+ $c->component('Mode', qw/foo3 bar3/);
is_deeply($args, [qw/foo3 bar3/], 'args passed to ACCEPT_CONTEXT ok');
}
-use Test::More tests => 44;
+use Test::More tests => 45;
use strict;
use warnings;
{
my $args;
- no warnings;
- *MyApp::Model::M::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
- *MyApp::View::V::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
+ {
+ no warnings 'once';
+ *MyApp::Model::M::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
+ *MyApp::View::V::ACCEPT_CONTEXT = sub { my ($self, $c, @args) = @_; $args= \@args};
+ }
- MyApp->model('M', qw/foo bar/);
+ my $c = bless {}, 'MyApp';
+
+ $c->model('M', qw/foo bar/);
is_deeply($args, [qw/foo bar/], '$c->model args passed to ACCEPT_CONTEXT ok');
- my $x = MyApp->view('V', qw/foo2 bar2/);
+ my $x = $c->view('V', qw/foo2 bar2/);
is_deeply($args, [qw/foo2 bar2/], '$c->view args passed to ACCEPT_CONTEXT ok');
# regexp fallback
- MyApp->view('::View::V', qw/foo3 bar3/);
+ $c->view('::View::V', qw/foo3 bar3/);
is_deeply($args, [qw/foo3 bar3/], 'args passed to ACCEPT_CONTEXT ok');
+
+ undef $args;
+ MyApp->model('M', qw/foo bar/);
+ is($args, undef, 'MyApp->model does not invoke ACCEPT_CONTEXT');
}