From: Marcus Ramberg Date: Sun, 7 Sep 2008 13:04:19 +0000 (+0000) Subject: Merge 'trunk' into 'Catalyst-Test-Updates' X-Git-Tag: 5.8000_03~67^2~1 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=commitdiff_plain;h=537546eb7c43571bf46c086b9a887ba2750311d2;hp=e8d0f69a4f830417edd8c13c6474d0856336c2d4 Merge 'trunk' into 'Catalyst-Test-Updates' r26476@Command-Central (orig r8329): zarquon | 2008-09-02 14:01:11 +0200 r13852@zaphod: kd | 2008-09-02 12:52:50 +0100 rafl doc improvements r26477@Command-Central (orig r8330): zarquon | 2008-09-02 14:04:57 +0200 r13854@zaphod: kd | 2008-09-02 13:04:40 +0100 rafl's doc improvements in 5.8 r26481@Command-Central (orig r8334): groditi | 2008-09-03 01:54:43 +0200 only call ACCEPT_CONTEXT if we actually have a context r26484@Command-Central (orig r8337): rafl | 2008-09-03 08:03:36 +0200 Fix ACCEPT_COMPONENT tests. As of r8334 MyApp->component doesn't invoke ACCEPT_COMPONENT anymore. r26485@Command-Central (orig r8338): rafl | 2008-09-03 08:03:41 +0200 Test MyApp->component not invoking ACCEPT_CONTEXT. r26487@Command-Central (orig r8340): rafl | 2008-09-03 10:38:05 +0200 Use Test::NoTabs instead of Test::Perl::Critic. r26507@Command-Central (orig r8359): rafl | 2008-09-05 17:50:16 +0200 Make go('/chained/action') execute the full chain, not just the endpoint. r26508@Command-Central (orig r8360): rafl | 2008-09-05 20:55:52 +0200 Fix ROADMAP url. --- diff --git a/Changes b/Changes index 0d2e92d..205b601 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,7 @@ - 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 diff --git a/Makefile.PL b/Makefile.PL index 00470d7..29dd6f8 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -34,7 +34,7 @@ requires 'Text::Balanced'; # core in 5.8.x but mentioned for completeness 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; diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index 8eb5838..b0d30d7 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -506,7 +506,7 @@ sub _comp_names { 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 ); } diff --git a/lib/Catalyst/DispatchType.pm b/lib/Catalyst/DispatchType.pm index 31b980c..06905ad 100644 --- a/lib/Catalyst/DispatchType.pm +++ b/lib/Catalyst/DispatchType.pm @@ -58,6 +58,8 @@ arrayref, or undef if unable to do so. sub uri_for_action { } +sub expand_action { } + =head1 AUTHORS Catalyst Contributors, see Catalyst.pm diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index 2030d40..a7d08a3 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -319,6 +319,23 @@ sub uri_for_action { } +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 @@ -496,13 +513,18 @@ with C would bind to C. 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 @@ -525,6 +547,19 @@ with the path of the current controller namespace, namely C. That action chains directly to C, so the C 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. + =item CaptureArgs Must be specified for every part of the chain that is not an diff --git a/lib/Catalyst/Dispatcher.pm b/lib/Catalyst/Dispatcher.pm index b4e3dc2..91ae6fc 100644 --- a/lib/Catalyst/Dispatcher.pm +++ b/lib/Catalyst/Dispatcher.pm @@ -178,6 +178,8 @@ sub go { return 0; } + $action = $self->expand_action($action); + local $c->request->{arguments} = $args; $c->namespace($action->namespace); $c->action($action); @@ -421,6 +423,17 @@ sub uri_for_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 diff --git a/lib/Catalyst/ROADMAP.pod b/lib/Catalyst/ROADMAP.pod index 7c79f7c..c7b1b54 100644 --- a/lib/Catalyst/ROADMAP.pod +++ b/lib/Catalyst/ROADMAP.pod @@ -4,7 +4,7 @@ This is a living document, that represents the core team's current plans 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. diff --git a/t/04critic.rc b/t/04critic.rc deleted file mode 100644 index 412f770..0000000 --- a/t/04critic.rc +++ /dev/null @@ -1,5 +0,0 @@ -include = CodeLayout::ProhibitHardTabs -only = 1 - -[CodeLayout::ProhibitHardTabs] -allow_leading_tabs = 0 \ No newline at end of file diff --git a/t/04critic.t b/t/04critic.t index d94c165..5a4a226 100644 --- a/t/04critic.t +++ b/t/04critic.t @@ -9,14 +9,13 @@ if ( !-e "$FindBin::Bin/../MANIFEST.SKIP" ) { 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/); diff --git a/t/unit_core_component.t b/t/unit_core_component.t index 250960a..368f163 100644 --- a/t/unit_core_component.t +++ b/t/unit_core_component.t @@ -73,16 +73,20 @@ is_deeply([ MyApp->comp('Foo') ], \@complist, 'Fallthrough return ok'); { 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'); } diff --git a/t/unit_core_mvc.t b/t/unit_core_mvc.t index 549d758..f77e263 100644 --- a/t/unit_core_mvc.t +++ b/t/unit_core_mvc.t @@ -1,4 +1,4 @@ -use Test::More tests => 44; +use Test::More tests => 45; use strict; use warnings; @@ -150,17 +150,25 @@ is ( MyApp->model , 'MyApp::Model::M', 'default_model in class method ok'); { 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'); }