revert MyApp instantiation
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Component.pm
CommitLineData
158c88c0 1package Catalyst::Component;
2
6f1f968a 3use MRO::Compat;
4use mro 'c3';
a7caa492 5use Moose;
6use MooseX::Adopt::Class::Accessor::Fast;
e8b9f2a9 7use Catalyst::Utils;
5595dd2f 8
158c88c0 9
a7caa492 10with 'MooseX::Emulate::Class::Accessor::Fast';
11with 'Catalyst::ClassData';
12
0fc2d522 13no Moose;
a7caa492 14
158c88c0 15=head1 NAME
16
17Catalyst::Component - Catalyst Component Base Class
18
19=head1 SYNOPSIS
20
21 # lib/MyApp/Model/Something.pm
22 package MyApp::Model::Something;
23
e7f1cf73 24 use base 'Catalyst::Component';
158c88c0 25
26 __PACKAGE__->config( foo => 'bar' );
27
28 sub test {
29 my $self = shift;
30 return $self->{foo};
31 }
32
33 sub forward_to_me {
34 my ( $self, $c ) = @_;
35 $c->response->output( $self->{foo} );
36 }
ac5c933b 37
158c88c0 38 1;
39
40 # Methods can be a request step
41 $c->forward(qw/MyApp::Model::Something forward_to_me/);
42
43 # Or just methods
44 print $c->comp('MyApp::Model::Something')->test;
45
46 print $c->comp('MyApp::Model::Something')->{foo};
47
48=head1 DESCRIPTION
49
ac5c933b 50This is the universal base class for Catalyst components
158c88c0 51(Model/View/Controller).
52
53It provides you with a generic new() for instantiation through Catalyst's
54component loader with config() support and a process() method placeholder.
55
7cd1a42b 56=cut
158c88c0 57
e8b9f2a9 58__PACKAGE__->mk_classdata($_) for qw/_config _plugins/;
59
0fc2d522 60sub new {
158c88c0 61 my ( $self, $c ) = @_;
62
63 # Temporary fix, some components does not pass context to constructor
64 my $arguments = ( ref( $_[-1] ) eq 'HASH' ) ? $_[-1] : {};
e8b9f2a9 65
a7caa492 66 my $args = $self->merge_config_hashes( $self->config, $arguments );
0fc2d522 67 $self->next::method( $args );
68}
158c88c0 69
22247e54 70sub COMPONENT {
71 my ( $self, $c ) = @_;
72
73 # Temporary fix, some components does not pass context to constructor
74 my $arguments = ( ref( $_[-1] ) eq 'HASH' ) ? $_[-1] : {};
0fc2d522 75
76
77 #this is not the EXACT logic we had before, since the original tested
78 #for a true value before returning meaning that a subsequent COMPONENT
79 #call could return undef and that would trigger a try to new, which could
80 #again return undef, which would lead to a straight bless of the args and
81 #config. I did not mantain that behavior because it did not seemed sane
82 # please rip me a new one if you have reason to believe i am being stupid
83 # --groditi
84 return $self->next::can ?
85 $self->next::method($c, $arguments) : $self->new($c, $arguments);
22247e54 86}
87
158c88c0 88sub config {
89 my $self = shift;
300633a8 90 my $config_sub = $self->can('_config');
e8b9f2a9 91 my $config = $self->$config_sub() || {};
158c88c0 92 if (@_) {
baf6a3db 93 my $newconfig = { %{@_ > 1 ? {@_} : $_[0]} };
94 $self->_config(
95 $self->merge_config_hashes( $config, $newconfig )
96 );
300633a8 97 } else {
98 # this is a bit of a kludge, required to make
99 # __PACKAGE__->config->{foo} = 'bar';
100 # work in a subclass. Calling the Class::Data::Inheritable setter
101 # will create a new _config method in the current class if it's
102 # currently inherited from the superclass. So, the can() call will
103 # return a different subref in that case and that means we know to
104 # copy and reset the value stored in the class data.
105
106 $self->_config( $config );
107
108 if ((my $config_sub_now = $self->can('_config')) ne $config_sub) {
109
110 $config = $self->merge_config_hashes( $config, {} );
111 $self->$config_sub_now( $config );
112 }
158c88c0 113 }
5e707396 114 return $config;
158c88c0 115}
116
7cd1a42b 117sub merge_config_hashes {
118 my ( $self, $lefthash, $righthash ) = @_;
158c88c0 119
7cd1a42b 120 return Catalyst::Utils::merge_hashes( $lefthash, $righthash );
121}
158c88c0 122
123sub process {
124
125 Catalyst::Exception->throw( message => ( ref $_[0] || $_[0] )
126 . " did not override Catalyst::Component::process" );
127}
128
7cd1a42b 1291;
baf6a3db 130
7cd1a42b 131__END__
baf6a3db 132
7cd1a42b 133=head1 METHODS
baf6a3db 134
7cd1a42b 135=head2 new($c, $arguments)
baf6a3db 136
7cd1a42b 137Called by COMPONENT to instantiate the component; should return an object
138to be stored in the application's component hash.
139
140=head2 COMPONENT($c, $arguments)
141
142If this method is present (as it is on all Catalyst::Component subclasses,
143it is called by Catalyst during setup_components with the application class
144as $c and any config entry on the application for this component (for example,
145in the case of MyApp::Controller::Foo this would be
ac5c933b 146MyApp->config->{'Controller::Foo'}). The arguments are expected to be a
147hashref and are merged with the __PACKAGE__->config hashref before calling
7cd1a42b 148->new to instantiate the component.
149
150=head2 $c->config
151
152=head2 $c->config($hashref)
153
154=head2 $c->config($key, $value, ...)
155
ac5c933b 156Accessor for this component's config hash. Config values can be set as
7cd1a42b 157key value pair, or you can specify a hashref. In either case the keys
ac5c933b 158will be merged with any existing config settings. Each component in
7cd1a42b 159a Catalyst application has it's own config hash.
160
161=head2 $c->process()
162
163This is the default method called on a Catalyst component in the dispatcher.
ac5c933b 164For instance, Views implement this action to render the response body
7cd1a42b 165when you forward to them. The default is an abstract method.
166
167=head2 $c->merge_config_hashes( $hashref, $hashref )
168
169Merges two hashes together recursively, giving right-hand precedence.
170Alias for the method in L<Catalyst::Utils>.
baf6a3db 171
825dbf85 172=head1 OPTIONAL METHODS
173
174=head2 ACCEPT_CONTEXT($c, @args)
175
176Catalyst components are normally initalized during server startup, either
177as a Class or a Instance. However, some components require information about
178the current request. To do so, they can implement an ACCEPT_CONTEXT method.
179
180If this method is present, it is called during $c->comp/controller/model/view
181with the current $c and any additional args (e.g. $c->model('Foo', qw/bar baz/)
182would cause your MyApp::Model::Foo instance's ACCEPT_CONTEXT to be called with
183($c, 'bar', 'baz')) and the return value of this method is returned to the
184calling code in the application rather than the component itself.
185
158c88c0 186=head1 SEE ALSO
187
e7f1cf73 188L<Catalyst>, L<Catalyst::Model>, L<Catalyst::View>, L<Catalyst::Controller>.
158c88c0 189
190=head1 AUTHOR
191
192Sebastian Riedel, C<sri@cpan.org>
193Marcus Ramberg, C<mramberg@cpan.org>
194Matt S Trout, C<mst@shadowcatsystems.co.uk>
195
196=head1 COPYRIGHT
197
198This program is free software, you can redistribute it and/or modify it under
199the same terms as Perl itself.
200
85d9fce6 201=cut