fixed issue when injecting controllers
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Component / DelayedInstance.pm
CommitLineData
3e560748 1package Catalyst::Component::DelayedInstance;
2
3use Moose::Role;
4
5around 'COMPONENT', sub {
6 my ($orig, $class, $app, $conf) = @_;
7 my $method = $class->can('build_delayed_instance') ?
8 'build_delayed_instance' : 'COMPONENT';
9
10 return bless sub { my $c = shift; $class->$method($app, $conf) }, $class;
11};
12
13our $SINGLE;
14
15sub ACCEPT_CONTEXT {
16 my ($self, $c, @args) = @_;
17 $c->log->warn("Component ${\$self->catalyst_component_name} cannot be called with arguments")
18 if $c->debug and scalar(@args) > 0;
19
20 return $SINGLE ||= $self->();
21}
22
23sub AUTOLOAD {
24 my ($self, @args) = @_;
25 my $method = our $AUTOLOAD;
26 $method =~ s/.*:://;
27
28 warn $method;
29 use Devel::Dwarn;
30 Dwarn \@args;
31
32 return ($SINGLE ||= $self->())->$method(@args);
33}
34
351;
36
37=head1 NAME
38
39Catalyst::Component::DelayedInstance - Moose Role for components which setup
40
41=head1 SYNOPSIS
42
43 package MyApp::Model::Foo;
44
45 use Moose;
46 extends 'Catalyst::Model';
47 with 'Catalyst::Component::DelayedInstance';
48
49 sub build_per_application_instance {
50 my ($class, $app, $config) = @_;
51
52 $config->{bar} = $app->model("Baz");
53 return $class->new($config);
54 }
55
56=head1 DESCRIPTION
57
58Sometimes you want an application scoped component that nevertheless needs other
59application components as part of its setup. In the past this was not reliable
60since Application scoped components are setup in linear order. You could not
61call $app->model in a COMPONENT method and expect 'Foo' to be there. This role
62defers creating the application scoped instance until after your application is
63fully setup. This means you can now assume your other application scoped components
64(components that do COMPONENT but not ACCEPT_CONTEXT) are available as dependencies.
65
66Please note this means that your instance is not created until the first time its
67called in a request. As a result any errors with configuration will not show up
68until later in runtime. So there is a larger burden on your testing to make sure
69your application startup and runtime is accurate. Also note that even though your
70instance creation is deferred to request time, the request context is NOT given,
71but the application is (this means that you cannot depend on components that do
72ACCEPT_CONTEXT, since you don't have one...).
73
74=head1 ATTRIBUTES
75
76=head1 METHODS
77
78=head2 ACCEPT_CONTEXT
79
80=head2 AUTOLOAD
81
82=head1 SEE ALSO
83
84L<Catalyst::Component>,
85
86=head1 AUTHORS
87
88See L<Catalyst>.
89
90=head1 COPYRIGHT
91
92See L<Catalyst>.
93
94=cut