As per usual, I mean maybe::next::method
[catagits/Catalyst-Component-ACCEPT_CONTEXT.git] / lib / Catalyst / Component / ACCEPT_CONTEXT.pm
CommitLineData
6166f03d 1package Catalyst::Component::ACCEPT_CONTEXT;
75f37967 2
6166f03d 3use warnings;
75f37967 4use strict;
ff05bc31 5use MRO::Compat;
75f37967 6use Scalar::Util qw(weaken);
6166f03d 7
8=head1 NAME
9
75f37967 10Catalyst::Component::ACCEPT_CONTEXT - Make the current Catalyst
11request context available in Models and Views.
12
13=head1 VERSION
14
15Version 0.05
16
17=cut
18
19our $VERSION = '0.05';
20
21=head1 SYNOPSIS
22
23Models and Views don't usually have access to the request object,
24since they probably don't really need it. Sometimes, however, having
25the request context available outside of Controllers makes your
26application cleaner. If that's the case, just use this module as a
27base class:
28
29 package MyApp::Model::Foobar;
30 use base qw|Catalyst::Component::ACCEPT_CONTEXT Catalyst::Model|;
31
32Then, you'll be able to get the current request object from within
33your model:
34
35 sub do_something {
36 my $self = shift;
37 print "The current URL is ". $self->context->req->uri->as_string;
38 }
39
a10b37c1 40=head1 WARNING WARNING WARNING
41
42Using this module is somewhat of a hack. Changing the state of your
43objects on every request is a pretty braindead way of doing OO. If
44you want your application to be brain-live, then you should use
45L<Catalyst::Component::InstancePerContext|Catalyst::Component::InstancePerContext>.
46
47Instead of doing this on every request (which is basically
48what this module does):
49
50 $my_component->context($c);
51
52It's better to do something like this:
53
54 package FooApp::Controller::Root;
55 use base 'Catalyst::Controller';
56 use Moose;
57
58 with 'Catalyst::Component::InstancePerContext';
59 has 'context' => (is => 'ro');
60
61 sub build_per_context_instance {
62 my ($self, $c, @args) = @_;
63 return $self->new({ context => $c, %$self, @args });
64 }
65
66 sub actions :Whatever {
67 my $self = shift;
68 my $c = $self->context; # this works now
69 }
70
71 1;
72
73Now you get a brand new object that lasts for a single request instead
74of changing the state of an existing one on each request. This is
75much cleaner OO design.
76
77The best strategy, though, is not to use the context inside your
78model. It's best for your Controller to pull the necessary data from
79the context, and pass it as arguments:
80
81 sub action :Local {
82 my ($self, $c) = @_;
83 my $foo = $c->model('Foo');
84 my $quux = $foo->frobnicate(baz => $c->request->params->{baz});
85 $c->stash->{quux} = $quux;
86 }
87
88This will make it Really Easy to test your components outside of
89Catalyst, which is always good.
90
75f37967 91=head1 METHODS
92
93=head2 context
94
95Returns the current request context.
96
97=cut
98
99sub context {
100 return shift->{context};
101}
102
103=head2 ACCEPT_CONTEXT
104
105Catalyst calls this method to give the current context to your model.
106You should never call it directly.
107
108Note that a new instance of your component isn't created. All we do
109here is shove C<$c> into your component. ACCEPT_CONTEXT allows for
110other behavior that may be more useful; if you want something else to
111happen just implement it yourself.
112
113See L<Catalyst::Component> for details.
114
115=cut
116
117sub ACCEPT_CONTEXT {
118 my $self = shift;
119 my $context = shift;
120
121 $self->{context} = $context;
122 weaken($self->{context});
ff05bc31 123
16beaa34 124 return $self->maybe::next::method($context, @_) || $self;
75f37967 125}
126
127=head2 COMPONENT
128
129Overridden to use initial application object as context before a request.
130
131=cut
132
133sub COMPONENT {
134 my $class = shift;
135 my $app = shift;
136 my $args = shift;
137 $args->{context} = $app;
138 weaken($args->{context}) if ref $args->{context};
16beaa34 139 return $class->maybe::next::method($app, $args, @_);
75f37967 140}
141
142=head1 AUTHOR
143
144Jonathan Rockway, C<< <jrockway at cpan.org> >>
145
146=head1 BUGS
147
148Please report any bugs or feature requests to
149C<bug-catalyst-component-accept_context at rt.cpan.org>, or through the web interface at
150L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Component-ACCEPT_CONTEXT>.
151I will be notified, and then you'll automatically be notified of progress on
152your bug as I make changes.
153
154=head1 SUPPORT
155
156You can find documentation for this module with the perldoc command.
157
158 perldoc Catalyst::Component::ACCEPT_CONTEXT
159
160You can also look for information at:
161
162=over 4
163
164=item * Catalyst Website
165
166L<http://www.catalystframework.org/>
167
168=item * AnnoCPAN: Annotated CPAN documentation
169
170L<http://annocpan.org/dist/Catalyst-Component-ACCEPT_CONTEXT>
171
172=item * CPAN Ratings
173
174L<http://cpanratings.perl.org/d/Catalyst-Component-ACCEPT_CONTEXT>
175
176=item * RT: CPAN's request tracker
177
178L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Component-ACCEPT_CONTEXT>
179
180=item * Search CPAN
181
182L<http://search.cpan.org/dist/Catalyst-Component-ACCEPT_CONTEXT>
183
184=back
185
186=head1 COPYRIGHT & LICENSE
187
188Copyright 2007 Jonathan Rockway.
189
190This program is free software; you can redistribute it and/or modify it
191under the same terms as Perl itself.
6166f03d 192
193=cut
194
75f37967 1951; # End of Catalyst::Component::ACCEPT_CONTEXT