File Coverage

blib/lib/Catalyst/Model/Curio.pm
Criterion Covered Total %
statement 47 47 100.0
branch 5 6 83.3
condition 3 3 100.0
subroutine 12 12 100.0
pod n/a
total 67 68 98.5


line stmt bran cond sub pod time code
1             package Catalyst::Model::Curio;
2             our $VERSION = '0.02';
3              
4             =encoding utf8
5              
6             =head1 NAME
7              
8             Catalyst::Model::Curio - Curio Model for Catalyst.
9              
10             =head1 SYNOPSIS
11              
12             Create your model class:
13              
14             package MyApp::Model::Cache;
15            
16             use Moo;
17             use strictures 2;
18             use namespace::clean;
19            
20             extends 'Catalyst::Model::Curio';
21            
22             __PACKAGE__->config(
23             class => 'MyApp::Service::Cache',
24             );
25            
26             1;
27              
28             Then use it in your controllers:
29              
30             my $chi = $c->model('Cache::geo_ip')->chi();
31              
32             See L<Curio/SYNOPSIS> as this SYNOPSIS is based on it.
33              
34             =head1 DESCRIPTION
35              
36             This module glues L<Curio> classes into Catalyst's model system.
37              
38             This distribution also comes with L<Catalyst::Helper::Model::Curio>
39             which makes it somewhat simpler to create your Catalyst model class.
40              
41             You may want to check out L<Curio/Use Curio Directly> for an
42             alternative viewpoint on using Catalyst models when you are
43             already using Curio.
44              
45             =cut
46              
47 1     1   2492374 use Curio qw();
  1         138950  
  1         24  
48 1     1   8 use Module::Runtime qw( require_module );
  1         2  
  1         4  
49 1     1   42 use Types::Common::String qw( NonEmptySimpleStr );
  1         2  
  1         10  
50 1     1   468 use Types::Standard qw( Bool );
  1         2  
  1         6  
51              
52 1     1   598 use Moo;
  1         1  
  1         5  
53 1     1   1982 use strictures 2;
  1         4  
  1         31  
54 1     1   134 use namespace::clean;
  1         2  
  1         4  
55              
56             extends 'Catalyst::Model';
57              
58             our $_KEY;
59              
60             my %installed_key_model_classes;
61              
62             sub BUILD {
63 3     3   80404 my ($self) = @_;
64              
65             # Get the Curio class loaded early.
66 3         16 require_module( $self->class() );
67              
68 3         28510 $self->_install_key_models();
69              
70 3         29 return;
71             }
72              
73             sub ACCEPT_CONTEXT {
74 9     9   208634 my ($self) = @_;
75              
76 9         48 my $method = $self->method();
77              
78 9   100     99 my $key = $self->key() || $_KEY;
79              
80 9 100       115 return $self->class->$method(
81             $key ? $key : (),
82             );
83             }
84              
85             sub _install_key_models {
86 3     3   9 my ($self) = @_;
87              
88 3 100       15 return if $self->key();
89              
90 2         16 my $model_class = ref( $self );
91 2 50       7 return if $installed_key_model_classes{ $model_class };
92              
93 2         4 my $model_name = $model_class;
94 2         13 $model_name =~ s{^.*::(?:Model|M)::}{};
95              
96 2         5 foreach my $key (@{ $self->class->declared_keys() }) {
  2         6  
97 1     1   405 no strict 'refs';
  1         2  
  1         147  
98              
99 5         38 *{"$model_class\::$key\::ACCEPT_CONTEXT"} = sub{
100 3     3   62533 my ($self, $c) = @_;
101 3         11 local $_KEY = $key;
102 3         19 return $c->model( $model_name );
103 5         61 };
104             }
105              
106 2         7 $installed_key_model_classes{ $model_class } = 1;
107              
108 2         6 return;
109             }
110              
111             =head1 CONFIG ARGUMENTS
112              
113             =head2 class
114              
115             class => 'MyApp::Service::Cache',
116              
117             The Curio class that this model wraps around.
118              
119             This is required to be set, otherwise Catalyst will throw
120             and exception when trying to load your model.
121              
122             =cut
123              
124             has class => (
125             is => 'ro',
126             isa => NonEmptySimpleStr,
127             required => 1,
128             );
129              
130             =head2 key
131              
132             key => 'geo_ip',
133              
134             If your Curio class supports keys then, if set, this forces
135             your model to interact with one key only.
136              
137             =cut
138              
139             has key => (
140             is => 'ro',
141             isa => NonEmptySimpleStr,
142             );
143              
144             =head2 method
145              
146             method => 'connect',
147              
148             By default Catalyst's C<model()> will call the C<fetch()>
149             method on your L</class> which will return a Curio object.
150             If you'd like, you can change this to call a different
151             method, returning something else of your choice.
152              
153             You could, for example, have a method in your Curio class
154             which returns the the resource that your Curio object makes:
155              
156             sub connect {
157             my $class = shift;
158             return $class->fetch( @_ )->chi();
159             }
160              
161             Then set the C<method> to C<connect> causing C<model()> to
162             return the CHI object instead of the Curio object.
163              
164             =cut
165              
166             has method => (
167             is => 'ro',
168             isa => NonEmptySimpleStr,
169             default => 'fetch',
170             );
171              
172             1;
173             __END__
174              
175             =head1 HANDLING KEYS
176              
177             =head2 No Keys
178              
179             A Curio class which does not support keys just means you don't
180             set the L</key> config argument.
181              
182             =head2 Single Key
183              
184             If your Curio class does support keys you can choose to create a model
185             for each key you want exposed in catalyst by specifying the L</key>
186             config argument in each model for each key you want available in Catalyst.
187             Each model would have the same L</class>.
188              
189             =head2 Multiple Keys
190              
191             If your Curio class supports keys and you do not set the L</key>
192             config argument then the model will automatically create pseudo
193             models for each key.
194              
195             This is done by appending each declared key to your model name.
196             You can see this in the L</SYNOPSIS> where the model name is
197             C<Cache> but since L</key> is not set, and the Curio class does
198             have declared keys then the way you get the model is by appending
199             C<::geo_ip> to the model name, or whatever key you want to access.
200              
201             =head1 SUPPORT
202              
203             Please submit bugs and feature requests to the
204             Catalyst-Model-Curio GitHub issue tracker:
205              
206             L<https://github.com/bluefeet/Catalyst-Model-Curio/issues>
207              
208             =head1 ACKNOWLEDGEMENTS
209              
210             Thanks to L<ZipRecruiter|https://www.ziprecruiter.com/>
211             for encouraging their employees to contribute back to the open
212             source ecosystem. Without their dedication to quality software
213             development this distribution would not exist.
214              
215             =head1 AUTHORS
216              
217             Aran Clary Deltac <bluefeet@gmail.com>
218              
219             =head1 COPYRIGHT AND LICENSE
220              
221             Copyright (C) 2019 Aran Clary Deltac
222              
223             This program is free software: you can redistribute it and/or modify
224             it under the terms of the GNU General Public License as published by
225             the Free Software Foundation, either version 3 of the License, or
226             (at your option) any later version.
227              
228             This program is distributed in the hope that it will be useful,
229             but WITHOUT ANY WARRANTY; without even the implied warranty of
230             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
231             GNU General Public License for more details.
232              
233             You should have received a copy of the GNU General Public License
234             along with this program. If not, see L<http://www.gnu.org/licenses/>.
235              
236             =cut
237