line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CatalystX::CRUD::ControllerRole; |
2
|
6
|
|
|
6
|
|
4365
|
use Moose::Role; |
|
6
|
|
|
|
|
18
|
|
|
6
|
|
|
|
|
88
|
|
3
|
6
|
|
|
6
|
|
36133
|
use Catalyst::Utils; |
|
6
|
|
|
|
|
22
|
|
|
6
|
|
|
|
|
4656
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
requires 'throw_error'; |
6
|
|
|
|
|
|
|
requires 'model_adapter'; |
7
|
|
|
|
|
|
|
requires 'model_name'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
has 'primary_key' => ( |
10
|
|
|
|
|
|
|
is => 'rw', |
11
|
|
|
|
|
|
|
isa => 'String', |
12
|
|
|
|
|
|
|
); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head2 get_primary_key( I<context>, I<pk_value> ) |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Should return an array of the name of the field(s) to fetch() I<pk_value> from |
17
|
|
|
|
|
|
|
and their respective values. |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
The default behaviour is to return B<primary_key> and the |
20
|
|
|
|
|
|
|
corresponding value(s) from I<pk_value>. |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
However, if you have other unique fields in your schema, you |
23
|
|
|
|
|
|
|
might return a unique field other than the primary key. |
24
|
|
|
|
|
|
|
This allows for a more flexible URI scheme. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
A good example is Users. A User record might have a numerical id (uid) |
27
|
|
|
|
|
|
|
and a username, both of which are unique. So if username 'foobar' |
28
|
|
|
|
|
|
|
has a B<primary_key> (uid) of '1234', both these URIs could fetch the same |
29
|
|
|
|
|
|
|
record: |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
/uri/for/user/1234 |
32
|
|
|
|
|
|
|
/uri/for/user/foobar |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
Again, the default behaviour is to return the B<primary_key> field name(s) |
35
|
|
|
|
|
|
|
from config() (accessed via $self->primary_key) but you can override |
36
|
|
|
|
|
|
|
get_primary_key() in your subclass to provide more flexibility. |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
If your primary key is composed of multiple columns, your return value |
39
|
|
|
|
|
|
|
should include all those columns and their values as extracted |
40
|
|
|
|
|
|
|
from I<pk_value>. Multiple values are assumed to be joined with C<;;>. |
41
|
|
|
|
|
|
|
See make_primary_key_string(). |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=cut |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub get_primary_key { |
46
|
35
|
|
|
35
|
1
|
101
|
my ( $self, $c, $id ) = @_; |
47
|
35
|
50
|
33
|
|
|
224
|
return () unless defined $id and length $id; |
48
|
35
|
|
|
|
|
161
|
my $pk = $self->primary_key; |
49
|
35
|
|
|
|
|
4660
|
my @ret; |
50
|
35
|
100
|
|
|
|
101
|
if ( ref $pk ) { |
51
|
1
|
|
|
|
|
8
|
my @val = split( m/;;/, $id ); |
52
|
1
|
|
|
|
|
3
|
for my $col (@$pk) { |
53
|
3
|
|
|
|
|
9
|
push( @ret, $col => shift(@val) ); |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
else { |
57
|
34
|
|
|
|
|
83
|
@ret = ( $pk => $id ); |
58
|
|
|
|
|
|
|
} |
59
|
35
|
|
|
|
|
134
|
return @ret; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head2 make_primary_key_string( I<object> ) |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Using value of B<primary_string> constructs a URI-ready |
65
|
|
|
|
|
|
|
string based on values in I<object>. I<object> is often |
66
|
|
|
|
|
|
|
the value of: |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
$c->stash->{object} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
but could be any object that has accessor methods with |
71
|
|
|
|
|
|
|
the same names as the field(s) specified by B<primary_key>. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Multiple values are joined with C<;;> and any C<;> or C</> characters |
74
|
|
|
|
|
|
|
in the column values are URI-escaped. |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=cut |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub make_primary_key_string { |
79
|
18
|
|
|
18
|
1
|
1070
|
my ( $self, $obj ) = @_; |
80
|
18
|
|
|
|
|
67
|
my $pk = $self->primary_key; |
81
|
18
|
|
|
|
|
2366
|
my $id; |
82
|
18
|
100
|
|
|
|
74
|
if ( ref $pk ) { |
83
|
1
|
|
|
|
|
2
|
my @vals; |
84
|
1
|
|
|
|
|
3
|
for my $field (@$pk) { |
85
|
2
|
|
|
|
|
16
|
my $v = scalar $obj->$field; |
86
|
2
|
50
|
|
|
|
15
|
$v = '' unless defined $v; |
87
|
2
|
|
|
|
|
10
|
$v =~ s/;/\%3b/g; |
88
|
2
|
|
|
|
|
6
|
push( @vals, $v ); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# if we had no vals, return undef |
92
|
1
|
50
|
|
|
|
2
|
if ( !grep {length} @vals ) { |
|
2
|
|
|
|
|
6
|
|
93
|
0
|
|
|
|
|
0
|
return $id; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
1
|
|
|
|
|
5
|
$id = join( ';;', @vals ); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
else { |
99
|
17
|
|
|
|
|
66
|
$id = $obj->$pk; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
18
|
50
|
|
|
|
2051
|
return $id unless defined $id; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# must escape any / in $id since passing it to uri_for as-is |
105
|
|
|
|
|
|
|
# will break. |
106
|
18
|
|
|
|
|
79
|
$id =~ s!/!\%2f!g; |
107
|
|
|
|
|
|
|
|
108
|
18
|
|
|
|
|
57
|
return $id; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=head2 instantiate_model_adapter( I<app_class> ) |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
If model_adapter() is set to a string of the adapter class |
114
|
|
|
|
|
|
|
name, this method will instantiate |
115
|
|
|
|
|
|
|
the model_adapter with its new() method, passing in |
116
|
|
|
|
|
|
|
model_name(), model_meta() and I<app_class>. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
sub instantiate_model_adapter { |
121
|
26
|
|
|
26
|
1
|
58
|
my $self = shift; |
122
|
26
|
50
|
|
|
|
76
|
my $app_class = shift or $self->throw_error("app_class required"); |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# if model_adapter class is defined, load and instantiate it. |
125
|
26
|
100
|
|
|
|
143
|
if ( $self->model_adapter ) { |
126
|
12
|
|
|
|
|
1670
|
Catalyst::Utils::ensure_class_loaded( $self->model_adapter ); |
127
|
12
|
|
|
|
|
1165
|
$self->model_adapter( |
128
|
|
|
|
|
|
|
$self->model_adapter->new( |
129
|
|
|
|
|
|
|
{ model_name => $self->model_name, |
130
|
|
|
|
|
|
|
model_meta => $self->model_meta, |
131
|
|
|
|
|
|
|
app_class => $app_class, |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
) |
134
|
|
|
|
|
|
|
); |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 do_model( I<context>, I<method>, I<args> ) |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Checks for presence of model_adapter() instance and calls I<method> on either model() |
141
|
|
|
|
|
|
|
or model_adapter() as appropriate. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
sub do_model { |
146
|
95
|
|
|
95
|
1
|
2101
|
my $self = shift; |
147
|
95
|
50
|
|
|
|
273
|
my $c = shift or $self->throw_error("context required"); |
148
|
95
|
50
|
|
|
|
235
|
my $method = shift or $self->throw_error("method required"); |
149
|
95
|
100
|
|
|
|
298
|
if ( $self->model_adapter ) { |
150
|
18
|
|
|
|
|
2435
|
return $self->model_adapter->$method( $self, $c, @_ ); |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
else { |
153
|
77
|
|
|
|
|
10187
|
return $c->model( $self->model_name )->$method(@_); |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head2 model_can( I<context>, I<method_name> ) |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Returns can() value from model_adapter() or model() as appropriate. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=cut |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub model_can { |
164
|
13
|
|
|
13
|
1
|
39
|
my $self = shift; |
165
|
13
|
50
|
|
|
|
36
|
my $c = shift or $self->throw_error("context required"); |
166
|
13
|
50
|
|
|
|
36
|
my $method = shift or $self->throw_error("method name required"); |
167
|
13
|
50
|
|
|
|
61
|
if ( $self->model_adapter ) { |
168
|
0
|
|
|
|
|
0
|
return $self->model_adapter->can($method); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
else { |
171
|
13
|
|
|
|
|
1824
|
return $c->model( $self->model_name )->can($method); |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
1; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
__END__ |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
=head1 AUTHOR |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
Peter Karman, C<< <perl at peknet.com> >> |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=head1 BUGS |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
186
|
|
|
|
|
|
|
C<bug-catalystx-crud at rt.cpan.org>, or through the web interface at |
187
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CatalystX-CRUD>. |
188
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
189
|
|
|
|
|
|
|
your bug as I make changes. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=head1 SUPPORT |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
perldoc CatalystX::CRUD |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
You can also look for information at: |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=over 4 |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=item * Mailing List |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
L<https://groups.google.com/forum/#!forum/catalystxcrud> |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
L<http://annocpan.org/dist/CatalystX-CRUD> |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=item * CPAN Ratings |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
L<http://cpanratings.perl.org/d/CatalystX-CRUD> |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=CatalystX-CRUD> |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=item * Search CPAN |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
L<http://search.cpan.org/dist/CatalystX-CRUD> |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
=back |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
Thanks to Zbigniew Lukasiak and Matt Trout for feedback and API ideas. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
Copyright 2007 Peter Karman, all rights reserved. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
232
|
|
|
|
|
|
|
under the same terms as Perl itself. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=cut |