File Coverage

blib/lib/Catalyst/Model/DataHash.pm
Criterion Covered Total %
statement 9 11 81.8
branch n/a
condition n/a
subroutine 3 5 60.0
pod n/a
total 12 16 75.0


line stmt bran cond sub pod time code
1             package Catalyst::Model::DataHash;
2              
3 1     1   430 use Moo;
  1         1  
  1         6  
4             our $VERSION = '0.001';
5              
6             extends 'Catalyst::Model';
7             with 'Catalyst::Component::InstancePerContext';
8             with 'Data::Perl::Role::Collection::Hash';
9              
10             sub build_per_context_instance {
11 1     1   85723 my ($self, $c, %args) = @_;
12 1         16 return $self->new(%args);
13             }
14              
15             around 'set', sub {
16             my ($orig, $self, %args) = @_;
17             foreach my $key (keys %args) {
18             die "'$key' already has a value: Can't set it again!"
19             if $self->exists($key);
20             }
21              
22             return $self->$orig(%args);
23             };
24              
25             around 'get', sub {
26             my ($orig, $self, @args) = @_;
27             foreach my $arg(@args) {
28             die "'$arg' has not yet been set: Can't get it!"
29             unless $self->exists($arg);
30             }
31              
32             return $self->$orig(@args);
33             };
34              
35             around 'delete', sub {
36             my ($orig, $self, @args) = @_;
37             foreach my $arg(@args) {
38             die "'$arg' has not yet been set: Can't delete it!"
39             unless $self->exists($arg);
40             }
41              
42             return $self->$orig(@args);
43             };
44              
45             around 'accessor', sub {
46             my ($orig, $self, $key, $maybe_value) = @_;
47             if(defined($key) && defined($maybe_value)) {
48             # attempt to set. Make sure doesn't already exist
49             die "'$key' already has a value"
50             if $self->exists($key);
51             } elsif(defined($key)) {
52             # attempt to get. Make sure there really is a value.
53             die "'$key' has not yet been set: Can't get it!"
54             unless $self->exists($key);
55             }
56              
57             return $self->$orig($key, $maybe_value);
58             };
59              
60 0     0   0 sub TO_JSON { +{shift->elements} }
61              
62             sub AUTOLOAD {
63 3     3   1391 my ($self, @args) = @_;
64 3         4 my $key = our $AUTOLOAD;
65 3         9 $key =~ s/.*:://;
66 3         50 return $self->get($key);
67             }
68            
69 0     0     sub DESTROY {}
70              
71             1;
72              
73             =head1 NAME
74              
75             Catalyst::Model::DataHash - Expose Perl::Data::Collection::Hash as a Per Request Model
76              
77             =head1 SYNOPSIS
78              
79             Create a Model Subclass:
80              
81             package MyApp::Model::Foo;
82              
83             use Moose;
84             extends 'Catalyst::Model::DataHash';
85              
86             __PACKAGE__->meta->make_immutable;
87              
88             Use it in a controller:
89              
90             sub myaction :Local {
91             my ($self, $c) = @_;
92              
93             # Default API
94             $c->model('DataHash')->set(a=>1, b=>2);
95             $c->model('DataHash')->get('a'); # 1
96             $c->model('DataHash')->get('b'); # 2
97              
98             # Alternative accessors
99             $c->model('DataHash')->a; # 1
100              
101             # RAISES AN EXCEPTION
102             $c->model('DataHash')->not_yet_set;
103             $c->model('DataHash')->set(a=>'already set...');
104             }
105              
106             You might find it useful to make this your default model:
107              
108             MyApp->config(default_model=>'DataHash');
109              
110             So that you can use this without naming the model:
111              
112             sub myaction :Local {
113             my ($self, $c) = @_;
114             $c->model->set(a=>1, b=>2);
115             $c->model->get('a'); # 1
116             $c->model->get('b'); # 2
117              
118             #alternative accessors
119             $c->model->a; # 1
120             }
121              
122             Which makes it less verbose. Alternatively you can use the included plugin
123             L<Catalyst::Plugin::DataHash> which injects a DataHash model for you into your
124             application, and sets it to be the default model:
125              
126             package MyApp;
127              
128             use Catalyst qw/DataHash/;
129              
130             MyApp->setup;
131              
132             Then you can just do (in an action):
133              
134             sub myaction :Local {
135             my ($self, $c) = @_;
136             $c->model->set(a=>1);
137             }
138              
139             =head1 DESCRIPTION
140              
141             The most common way that a controller shares information between actions and the
142             view is to set key / values in the stash:
143              
144             $c->stash(a=>1, b=>2);
145              
146             The stash suffers from several downsides, some of which include the fact it is
147             a global hash and is prone to typos and related confusion, like how it can auto-vivify
148             a stash key when a value does not already exist. This L<Catalyst>
149             model offers an approach to providing stash-like features with a slightly less
150             error prone interface. It is also hoped that it might inspire you to think about
151             how to better use models in your L<Catalyst> application to properly type your
152             interfaces. It wraps L<Perl::Data>, specifically L<Data::Perl::Collection::Hash>
153             and addes a bit of error checking and a method it ease integration with JSON encoders.
154              
155             This is a 'per-request' Catalyst model, which means that each new request can get one
156             model for use during the request duration.
157              
158             =head1 METHODS
159              
160             This model provides the following methods, most of which are delegated to
161             L<Data::Perl::Collection::Hash>. Most of this documention following is copied verbosely
162             from that distribution. When we'd adapted functionality, this is noted.
163              
164             =head2 set($key => $value, $key2 => $value2...)
165              
166             Sets the elements in the hash to the given values. It returns the new values set for each
167             key, in the same order as the keys passed to the method.
168              
169             This method requires at least two arguments, and expects an even number of arguments.
170              
171             B<Added Behavior>: If you try to set a key that already exists, this will raise an exception.
172              
173             =head2 get($key1, $key2, ...)
174              
175             Returns a list of values in the hash for the given keys.
176              
177             This method requires at least one argument.
178              
179             B<Added Behavior>: If you try to get a key that has not already been set, this will raise an
180             exception.
181              
182             =head2 keys
183              
184             Returns the list of keys in the hash.
185              
186             This method does not accept any arguments.
187              
188             =head2 delete($key, $key2, $key3...)
189             Removes the elements with the given keys.
190              
191             Returns a list of values in the hash for the deleted keys.
192              
193             B<Added Behavior>: If you try to delete a key that has not already been set, this will raise an
194             exception.
195              
196             =head2 exists($key)
197              
198             Returns true if the given key is present in the hash.
199              
200             This method requires a single argument.
201              
202             =head2 defined($key)
203              
204             Returns true if the value of a given key is defined.
205              
206             This method requires a single argument.
207              
208             =head2 values
209              
210             Returns the list of values in the hash.
211              
212             This method does not accept any arguments.
213              
214             =head2 kv
215              
216             Returns the key/value pairs in the hash as an array of array references.
217              
218             for my $pair ( $object->option_pairs ) {
219             print "$pair->[0] = $pair->[1]\n";
220             }
221              
222             This method does not accept any arguments.
223              
224             =head2 elements/all
225              
226             Returns the key/value pairs in the hash as a flattened list..
227              
228             This method does not accept any arguments.
229              
230             =head2 clear
231              
232             Resets the hash to an empty value, like %hash = ().
233              
234             This method does not accept any arguments.
235              
236             =head2 count
237              
238             Returns the number of elements in the hash.
239              
240             This method does not accept any arguments.
241              
242             =head2 accessor($key)
243              
244             =head2 accessor($key, $value)
245              
246             If passed one argument, returns the value of the specified key.
247             If passed two arguments, sets the value of the specified key.
248              
249             B<Added Behavior>: If you try to get a key that has not already been set, this will raise an
250             exception. If you try to set a key that has already been set, it will raise an exception.
251              
252             =head2 shallow_clone
253             This method returns a shallow clone of the hash reference. The return value is a
254             reference to a new hash with the same keys and values. It is shallow because any values
255             that were references in the original will be the same references in the clone.
256              
257             =head2 TO_JSON
258              
259             Returns a hashref of all the existing data suitable to send to a JSON serializer.
260              
261             =head1 SEE ALSO
262              
263             L<Catalyst>, L<Data::Perl>.
264              
265             =head1 AUTHOR
266            
267             John Napiorkowski L<email:jjnapiork@cpan.org>
268            
269             =head1 COPYRIGHT & LICENSE
270            
271             Copyright 2015, John Napiorkowski L<email:jjnapiork@cpan.org>
272            
273             This library is free software; you can redistribute it and/or modify it under
274             the same terms as Perl itself.
275              
276             =cut