File Coverage

blib/lib/Catalyst/ControllerPerContext.pm
Criterion Covered Total %
statement 3 24 12.5
branch 0 6 0.0
condition 0 11 0.0
subroutine 1 3 33.3
pod 2 2 100.0
total 6 46 13.0


line stmt bran cond sub pod time code
1             package Catalyst::ControllerPerContext;
2              
3             our $VERSION = '0.006';
4              
5 1     1   1331 use Moose;
  1         493314  
  1         10  
6             extends 'Catalyst::Controller';
7              
8             has 'ctx' => (is=>'ro', required=>1);
9              
10             sub COMPONENT {
11 0     0 1   my ($class, $app, $args) = @_;
12 0           $args = $class->merge_config_hashes($args, $class->_config);
13 0 0         $args = $class->process_component_args($app, $args) if $class->can('process_component_args');
14              
15             ## All this crazy will probably break if you do even more insane things
16 0           my $application_self = bless $args, $class;
17 0           $application_self->{_application} = $app;
18              
19 0   0       my $action = delete $args->{action} || {};
20 0   0       my $actions = delete $args->{actions} || {};
21 0           $application_self->{actions} = $application_self->merge_config_hashes($actions, $action);
22 0   0       $application_self->{_all_actions_attributes} = delete $application_self->{actions}->{'*'} || {};
23 0   0       $application_self->{_action_role_args} = delete($application_self->{action_roles}) || [];
24 0 0         $application_self->{path_prefix} = delete $application_self->{path} if exists $application_self->{path};
25 0           $application_self->{_action_roles} = $application_self->_build__action_roles;
26 0 0         $application_self->{action_namespace} = $application_self->{namespace} if exists $application_self->{namespace};
27              
28 0           return $application_self;
29             }
30              
31             sub ACCEPT_CONTEXT {
32 0     0 1   my $application_self = shift;
33 0           my $c = shift;
34              
35 0           my $class = ref($application_self);
36 0   0       my $self = $c->stash->{"__ControllerPerContext_${class}"} ||= do {
37 0           my %args = (%$application_self, ctx=>$c, @_);
38 0           $class->new($c, \%args);
39             };
40              
41 0           return $self;
42             }
43              
44             __PACKAGE__->meta->make_immutable;
45              
46             =head1 NAME
47            
48             Catalyst::ControllerPerContext - Context Scoped Controlelrs
49              
50             =head1 SYNOPSIS
51              
52             package Example::Controller::Register;
53              
54             use Moose;
55             use MooseX::MethodAttributes;
56              
57             extends 'Catalyst::ControllerPerRequest';
58              
59             has registration => (
60             is => 'ro',
61             lazy => 1,
62             required => 1,
63             default => sub($self) { $self->ctx->Model('Users')->registration },
64             );
65              
66             sub root :Chained(/root) PathPart(register) Args(0) {
67             my ($self, $c) = @_;
68             $self->registration;
69             }
70              
71             __PACKAGE__->meta->make_immutable;
72              
73             =head1 DESCRIPTION
74              
75             Classic L<Catalyst::Controller>s are application scoped, which means we create an instance of the
76             controller when the application starts as a singleton instance, which is reused for all request
77             going forward. This has the lowest overhead. However it makes it hard to do things like use
78             controller attributes since those attributes get shared for all requests. By changing to creating
79             a new controller for each request you can then use those attributes.
80              
81             This for the most part is nothing you couldn't do with the stash but has the upside of avoiding
82             the stash typo bugs you see a lot and also the stash is shared for the entire context so stuff
83             you stuff in there might be too broadly accessible, whereas data in controller attributes is
84             scoped to the controller only.
85              
86             I consider this an experimental release to let interested people (including myself) to play with
87             the idea of per context controllers and see if it leads to new approaches and better code. Please
88             be warned that the code under the hood here is a bit of a hack up due to how we added some features
89             to Controller over time that made the assumption that an attribute is application scoped (such as
90             how we merged the action role support many years ago). If this turns out to be a good idea we'll
91             need to make deeper fixes to the base L<Catalyst::Controller> to make this right. As a result of
92             this hacking I can't be sure this controller will be a drop in replacement everywhere, especially
93             if you've doing a ton of customization to the base controller code in a custom controller subclass.
94              
95             In order to emphasize the magnitude of this crime / hack there's not really many test cased ;)
96              
97             Some of the things I'm using this to experiement with is using controller attributes to define
98             a stronger API between the controller and its views and using controller attributes as proxies
99             for the models a controller works with.
100              
101             =head1 ALSO SEE
102            
103             L<Catalyst::Runtime>, L<Catalyst::Controller>
104              
105             =head1 AUTHOR
106              
107             John Napiorkowski <jjnapiork@cpan.org>
108              
109             =head1 COPYRIGHT
110            
111             2023
112              
113             =head1 LICENSE
114              
115             This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
116