File Coverage

blib/lib/Catalyst/Controller/ActionRole.pm
Criterion Covered Total %
statement 37 38 97.3
branch 6 6 100.0
condition 2 3 66.6
subroutine 10 15 66.6
pod 1 1 100.0
total 56 63 88.8


line stmt bran cond sub pod time code
1             package Catalyst::Controller::ActionRole;
2             our $VERSION = '0.04_01';
3              
4             # ABSTRACT: Apply roles to action instances
5              
6 2     2   3371592 use Moose;
  2         4  
  2         12  
7 2     2   9839 use Class::MOP;
  2         3  
  2         40  
8 2     2   9 use Catalyst::Utils;
  2         7  
  2         40  
9 2     2   7 use Moose::Meta::Class;
  2         2  
  2         90  
10 2     2   10 use String::RewritePrefix;
  2         2  
  2         21  
11 2     2   270 use MooseX::Types::Moose qw/ArrayRef RoleName/;
  2         2  
  2         24  
12              
13 2     2   7046 use namespace::clean -except => 'meta';
  2         2  
  2         22  
14              
15             extends 'Catalyst::Controller';
16              
17              
18             __PACKAGE__->mk_classdata(qw/_action_role_prefix/);
19             __PACKAGE__->_action_role_prefix('Catalyst::Action::Role::');
20              
21              
22             has _action_roles => (
23             is => 'ro',
24             isa => ArrayRef[RoleName],
25             init_arg => 'action_roles',
26             auto_deref => 1,
27             );
28              
29             # FIXME: this isn't what BUILDARGS was intended for. I guess the expansion
30             # should be done in a trigger.
31              
32             override BUILDARGS => sub {
33             my ($self) = @_;
34             my $args = super;
35             if (my $roles = $args->{action_roles}) {
36             my @roles = $self->_expand_role_shortname(@{ $roles });
37             Class::MOP::load_class($_) for @roles;
38             $args->{action_roles} = \@roles;
39             }
40             return $args;
41             };
42              
43             sub create_action {
44 28     28 1 119095 my ($self, %args) = @_;
45              
46             my $class = exists $args{attributes}->{ActionClass}
47 28 100       133 ? $args{attributes}->{ActionClass}->[0]
48             : $self->_action_class;
49              
50 28         966 Class::MOP::load_class($class);
51              
52 28 100       3658 my @roles = ($self->_action_roles, @{ $args{attributes}->{Does} || [] });
  28         143  
53 28 100       58 if (@roles) {
54 16         49 Class::MOP::load_class($_) for @roles;
55 16         32564 my $meta = Moose::Meta::Class->initialize($class)->create_anon_class(
56             superclasses => [$class],
57             roles => \@roles,
58             cache => 1,
59             );
60 16     0   41850 $meta->add_method(meta => sub { $meta });
  0     0   0  
        0      
        0      
        0      
61 16         572 $class = $meta->name;
62             }
63              
64 28         709 return $class->new(\%args);
65             }
66              
67             sub _expand_role_shortname {
68 8     8   21 my ($self, @shortnames) = @_;
69 8   66     76 my $app = Catalyst::Utils::class2appclass(blessed($self) || $self);
70              
71 8         129 return String::RewritePrefix->rewrite(
72             { '' => $self->_action_role_prefix,
73             '~' => qq{${app}::Action::Role::},
74             '+' => '' },
75             @shortnames,
76             );
77             }
78              
79             sub _parse_Does_attr {
80 6     6   16592 my ($self, $app, $name, $value) = @_;
81 6         27 return Does => $self->_expand_role_shortname($value);
82             }
83              
84             1;
85              
86             __END__
87             =head1 NAME
88              
89             Catalyst::Controller::ActionRole - Apply roles to action instances
90              
91             =head1 VERSION
92              
93             version 0.04_01
94              
95             =head1 SYNOPSIS
96              
97             package MyApp::Controller::Foo;
98              
99             use parent qw/Catalyst::Controller::ActionRole/;
100              
101             sub bar : Local Does('Moo') { ... }
102              
103             =head1 DESCRIPTION
104              
105             This module allows to apply roles to the C<Catalyst::Action>s for different
106             controller methods.
107              
108             For that a C<Does> attribute is provided. That attribute takes an argument,
109             that determines the role, which is going to be applied. If that argument is
110             prefixed with C<+>, it is assumed to be the full name of the role. If it's
111             prefixed with C<~>, the name of your application followed by
112             C<::Action::Role::> is prepended. If it isn't prefixed with C<+> or C<~>,
113             the value of the C<_action_role_prefix> attribute will be prepended.
114              
115             Additionally it's possible to to apply roles to B<all> actions of a controller
116             without specifying the C<Does> keyword in every action definition:
117              
118             package MyApp::Controller::Bar
119              
120             use parent qw/Catalyst::Controller::ActionRole/;
121              
122             __PACKAGE__->config(
123             action_roles => ['Foo', '~Bar'],
124             );
125              
126             sub moo : Local { ... } # has Catalyst::Action::Role::Foo and MyApp::Action::Role::Bar applied
127              
128             =head1 ATTRIBUTES
129              
130             =head2 _action_role_prefix
131              
132             This class attribute stores a string that is going to be prepended to all role
133             names if they aren't prefixed with C<+> or C<~>. It defaults to
134             C<Catalyst::Action::Role::>.
135              
136              
137              
138             =head2 _action_roles
139              
140             This attribute stores an array reference of role names that will be applied to
141             every action of this controller. It can be set by passing a C<action_roles>
142             argument to the constructor. The same expansions as for C<Does> will be
143             performed.
144              
145             =head1 AUTHOR
146              
147             Florian Ragwitz <rafl@debian.org>
148              
149             =head1 COPYRIGHT AND LICENSE
150              
151             This software is copyright (c) 2009 by Florian Ragwitz.
152              
153             This is free software; you can redistribute it and/or modify it under
154             the same terms as perl itself.
155