Bump versions, changelog for release
[catagits/Catalyst-Component-ACCEPT_CONTEXT.git] / lib / Catalyst / Component / ACCEPT_CONTEXT.pm
1 package Catalyst::Component::ACCEPT_CONTEXT;
2
3 use warnings;
4 use strict;
5 use MRO::Compat;
6 use Scalar::Util qw(weaken);
7
8 =head1 NAME
9
10 Catalyst::Component::ACCEPT_CONTEXT - Make the current Catalyst
11 request context available in Models and Views.
12
13 =head1 VERSION
14
15 Version 0.07
16
17 =cut
18
19 our $VERSION = '0.07';
20
21 =head1 SYNOPSIS
22
23 Models and Views don't usually have access to the request object,
24 since they probably don't really need it.  Sometimes, however, having
25 the request context available outside of Controllers makes your
26 application cleaner.  If that's the case, just use this module as a
27 base class:
28
29     package MyApp::Model::Foobar;
30     use base qw|Catalyst::Component::ACCEPT_CONTEXT Catalyst::Model|;
31
32 Then, you'll be able to get the current request object from within
33 your model:
34
35     sub do_something {
36         my $self = shift;
37         print "The current URL is ". $self->context->req->uri->as_string;
38     }
39
40 =head1 WARNING WARNING WARNING
41
42 Using this module is somewhat of a hack.  Changing the state of your
43 objects on every request is a pretty braindead way of doing OO.  If
44 you want your application to be brain-live, then you should use
45 L<Catalyst::Component::InstancePerContext>.
46
47 Instead of doing this on every request (which is basically
48 what this module does):
49
50     $my_component->context($c);
51
52 It'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
73 Now you get a brand new object that lasts for a single request instead
74 of changing the state of an existing one on each request.  This is
75 much cleaner OO design.
76
77 The best strategy, though, is not to use the context inside your
78 model.  It's best for your Controller to pull the necessary data from
79 the 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
88 This will make it Really Easy to test your components outside of
89 Catalyst, which is always good.
90
91 =head1 METHODS
92
93 =head2 context
94
95 Returns the current request context.
96
97 =cut
98
99 sub context {
100     return shift->{context};
101 }
102
103 =head2 ACCEPT_CONTEXT
104
105 Catalyst calls this method to give the current context to your model.
106 You should never call it directly.
107
108 Note that a new instance of your component isn't created.  All we do
109 here is shove C<$c> into your component.  ACCEPT_CONTEXT allows for
110 other behavior that may be more useful; if you want something else to
111 happen just implement it yourself.
112
113 See L<Catalyst::Component> for details.
114
115 =cut
116
117 sub ACCEPT_CONTEXT {
118     my $self    = shift;
119     my $context = shift;
120
121     $self->{context} = $context;
122     weaken($self->{context});
123
124     return $self->maybe::next::method($context, @_) || $self;
125 }
126
127 =head2 COMPONENT
128
129 Overridden to use initial application object as context before a request.
130
131 =cut
132
133 sub 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};
139     return $class->maybe::next::method($app, $args, @_);
140 }
141
142 =head1 AUTHOR
143
144 Jonathan Rockway, C<< <jrockway at cpan.org> >>
145
146 Patches contributed and maintained by:
147
148 =over
149
150 =item Rafael Kitover (Caelum)
151
152 =item Tomas Doran (t0m) C<< <bobtfish@bobtfish.net> >>
153
154 =back
155
156 =head1 BUGS
157
158 Please report any bugs or feature requests to
159 C<bug-catalyst-component-accept_context at rt.cpan.org>, or through the web interface at
160 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Catalyst-Component-ACCEPT_CONTEXT>.
161 I will be notified, and then you'll automatically be notified of progress on
162 your bug as I make changes.
163
164 =head1 SUPPORT
165
166 You can find documentation for this module with the perldoc command.
167
168     perldoc Catalyst::Component::ACCEPT_CONTEXT
169
170 You can also look for information at:
171
172 =over 4
173
174 =item * Catalyst Website
175
176 L<http://www.catalystframework.org/>
177
178 =item * AnnoCPAN: Annotated CPAN documentation
179
180 L<http://annocpan.org/dist/Catalyst-Component-ACCEPT_CONTEXT>
181
182 =item * CPAN Ratings
183
184 L<http://cpanratings.perl.org/d/Catalyst-Component-ACCEPT_CONTEXT>
185
186 =item * RT: CPAN's request tracker
187
188 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Catalyst-Component-ACCEPT_CONTEXT>
189
190 =item * Search CPAN
191
192 L<http://search.cpan.org/dist/Catalyst-Component-ACCEPT_CONTEXT>
193
194 =back
195
196 =head1 Source code
197
198 The source code for this project can be found at:
199
200     git://git.shadowcat.co.uk/catagits/Catalyst-Component-ACCEPT_CONTEXT
201
202 =head1 COPYRIGHT & LICENSE
203
204 Copyright 2007 Jonathan Rockway.
205
206 This program is free software; you can redistribute it and/or modify it
207 under the same terms as Perl itself.
208
209 =cut
210
211 1; # End of Catalyst::Component::ACCEPT_CONTEXT