Commit | Line | Data |
b8e6d226 |
1 | package DBIx::Class::ResultSet::WithMetaData; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Data::Alias; |
7 | use Moose; |
79b18b81 |
8 | use Method::Signatures::Simple; |
b8e6d226 |
9 | extends 'DBIx::Class::ResultSet'; |
10 | |
11 | has '_row_info' => ( |
683ececb |
12 | is => 'rw', |
13 | isa => 'HashRef' |
b8e6d226 |
14 | ); |
15 | |
16 | has 'was_row' => ( |
683ececb |
17 | is => 'rw', |
18 | isa => 'Int' |
b8e6d226 |
19 | ); |
20 | |
b51d39c8 |
21 | has 'id_cols' => ( |
683ececb |
22 | is => 'rw', |
23 | isa => 'ArrayRef', |
b51d39c8 |
24 | ); |
683ececb |
25 | |
b9495a50 |
26 | has '_hash_modifiers' => ( |
27 | is => 'rw', |
28 | isa => 'ArrayRef', |
29 | ); |
30 | |
31 | has '_key_modifiers' => ( |
f1690863 |
32 | is => 'rw', |
33 | isa => 'ArrayRef', |
34 | ); |
35 | |
683ececb |
36 | =head1 VERSION |
37 | |
099cfc0c |
38 | Version 1.000000 |
683ececb |
39 | |
40 | =cut |
41 | |
099cfc0c |
42 | our $VERSION = '1.000000'; |
683ececb |
43 | |
44 | =head1 NAME |
45 | |
46 | DBIx::Class::ResultSet::WithMetaData |
47 | |
48 | =head1 SYNOPSIS |
49 | |
50 | package MyApp::Schema::ResultSet::ObjectType; |
51 | |
52 | use Moose; |
53 | use MooseX::Method::Signatures; |
54 | extends 'DBIx::Class::ResultSet::WithMetaData; |
55 | |
56 | method with_substr () { |
50e9dd04 |
57 | return $self->_with_meta_key( |
58 | substr => sub { |
59 | return substr(shift->{name}, 0, 3); |
60 | } |
61 | ); |
683ececb |
62 | } |
63 | |
64 | ... |
65 | |
66 | |
67 | # then somewhere else |
68 | |
d1d2fc5e |
69 | my $object_type_arrayref = $object_type_rs->with_substr->display(); |
683ececb |
70 | |
71 | # [{ |
72 | # 'artistid' => '1', |
73 | # 'name' => 'Caterwauler McCrae', |
74 | # 'substr' => 'Cat' |
75 | # }, |
76 | # { |
77 | # 'artistid' => '2', |
78 | # 'name' => 'Random Boy Band', |
79 | # 'substr' => 'Ran' |
80 | # }, |
81 | # { |
82 | # 'artistid' => '3', |
83 | # 'name' => 'We Are Goth', |
84 | # 'substr' => 'We ' |
85 | # }] |
86 | |
87 | =head1 DESCRIPTION |
88 | |
89 | Attach metadata to rows by chaining ResultSet methods together. When the ResultSet is |
90 | flattened to an ArrayRef the attached metadata is merged with the row hashes to give |
91 | a combined 'hash-plus-other-stuff' representation. |
92 | |
93 | =head1 METHODS |
94 | |
95 | =cut |
b51d39c8 |
96 | |
b8e6d226 |
97 | sub new { |
683ececb |
98 | my $self = shift; |
b51d39c8 |
99 | |
683ececb |
100 | my $new = $self->next::method(@_); |
b9495a50 |
101 | foreach my $key (qw/_row_info was_row id_cols _key_modifiers _hash_modifiers/) { |
683ececb |
102 | alias $new->{$key} = $new->{attrs}{$key}; |
103 | } |
b8e6d226 |
104 | |
683ececb |
105 | unless ($new->_row_info) { |
106 | $new->_row_info({}); |
107 | } |
b8e6d226 |
108 | |
b9495a50 |
109 | unless ($new->_key_modifiers) { |
110 | $new->_key_modifiers([]); |
111 | } |
112 | unless ($new->_hash_modifiers) { |
113 | $new->_hash_modifiers([]); |
f1690863 |
114 | } |
115 | |
683ececb |
116 | unless ($new->id_cols && scalar(@{$new->id_cols})) { |
117 | $new->id_cols([sort $new->result_source->primary_columns]); |
118 | } |
b8e6d226 |
119 | |
683ececb |
120 | return $new; |
b8e6d226 |
121 | } |
122 | |
683ececb |
123 | =head2 display |
124 | |
125 | =over 4 |
126 | |
127 | =item Arguments: none |
128 | |
129 | =item Return Value: ArrayRef |
130 | |
131 | =back |
132 | |
133 | $arrayref_of_row_hashrefs = $rs->display(); |
134 | |
135 | This method uses L<DBIx::Class::ResultClass::HashRefInflator> to convert all |
136 | rows in the ResultSet to HashRefs. These are then merged with any metadata |
137 | that had been attached to the rows using L</add_row_info>. |
138 | |
139 | =cut |
140 | |
b8e6d226 |
141 | method display () { |
142 | my $rs = $self->search({}); |
143 | $rs->result_class('DBIx::Class::ResultClass::HashRefInflator'); |
144 | my @rows; |
683ececb |
145 | foreach my $row ($rs->all) { |
f1690863 |
146 | # THIS BLOCK IS DEPRECATED |
683ececb |
147 | if (my $info = $self->row_info_for(id => $self->_mk_id(row => $row))) { |
148 | $row = { %{$row}, %{$info} }; |
149 | } |
f1690863 |
150 | |
b9495a50 |
151 | foreach my $modifier (@{$rs->_hash_modifiers}) { |
152 | my $row_hash = $modifier->($row); |
153 | if (ref $row_hash ne 'HASH') { |
154 | die 'modifier subref (added via build_metadata) did not return hashref'; |
155 | } |
156 | |
157 | # simple merge for now, potentially needs to be more complex |
158 | $row->{$_} = $row_hash->{$_} for keys %{$row_hash}; |
159 | } |
160 | |
161 | foreach my $params (@{$rs->_key_modifiers}) { |
162 | my $modifier = $params->{modifier}; |
163 | my $key = $params->{key}; |
164 | |
165 | if (my $val = $modifier->($row)) { |
166 | $row->{$key} = $val; |
f1690863 |
167 | } |
f1690863 |
168 | } |
683ececb |
169 | push(@rows, $row); |
170 | } |
b8e6d226 |
171 | |
172 | return ($self->was_row) ? $rows[0] : \@rows; |
173 | } |
174 | |
b9495a50 |
175 | =head2 _with_meta_key |
f1690863 |
176 | |
177 | =over 4 |
178 | |
b9495a50 |
179 | =item Arguments: key_name => subref($row_hash) |
f1690863 |
180 | |
181 | =item Return Value: ResultSet |
182 | |
183 | =back |
184 | |
b9495a50 |
185 | $self->_with_meta_key( substr => sub ($row) { |
186 | return substr(shift->{name}, 0, 3); |
f1690863 |
187 | }); |
188 | |
b9495a50 |
189 | This method allows you populate a certain key for each row hash at L</display> time. |
f1690863 |
190 | |
191 | =cut |
192 | |
b9495a50 |
193 | method _with_meta_key ($key, $modifier) { |
194 | my $rs = $self->search({}); |
195 | unless ($key) { |
196 | die 'build_metadata called without key'; |
197 | } |
198 | |
f1690863 |
199 | unless ($modifier && (ref $modifier eq 'CODE')) { |
200 | die 'build_metadata called without modifier param'; |
201 | } |
202 | |
b9495a50 |
203 | push( @{$rs->_key_modifiers}, { key => $key, modifier => $modifier }); |
204 | return $rs; |
f1690863 |
205 | } |
206 | |
b9495a50 |
207 | =head2 _with_meta_hash |
208 | |
209 | =over 4 |
210 | |
211 | =item Arguments: subref($row_hash) |
212 | |
213 | =item Return Value: ResultSet |
214 | |
215 | =back |
216 | |
217 | $self->_with_meta_hash( sub ($row) { |
218 | my $row = shift; |
219 | my $return_hash = { substr => substr($row->{name}, 0, 3), substr2 => substr($row->{name}, 0, 4) }; |
220 | return $return_hash; |
221 | }); |
222 | |
223 | Use this method when you want to populate multiple keys of the hash at the same time. If you just want to |
224 | populate one key, use L</_with_meta_key>. |
225 | |
226 | =cut |
227 | |
228 | method _with_meta_hash ($modifier) { |
229 | my $rs = $self->search({}); |
230 | unless ($modifier && (ref $modifier eq 'CODE')) { |
231 | die 'build_metadata called without modifier param'; |
232 | } |
233 | |
234 | push( @{$rs->_hash_modifiers}, $modifier ); |
235 | return $rs; |
236 | } |
f1690863 |
237 | |
238 | =head2 add_row_info (DEPRECATED) |
683ececb |
239 | |
240 | =over 4 |
241 | |
242 | =item Arguments: row => DBIx::Class::Row object, info => HashRef to attach to the row |
243 | |
244 | =item Return Value: ResultSet |
245 | |
246 | =back |
247 | |
248 | $rs = $rs->add_row_info(row => $row, info => { dates => [qw/mon weds fri/] } ); |
249 | |
f1690863 |
250 | DEPRECATED - this method is quite slow as it requires that you iterate through |
251 | the resultset each time you want to add metadata. Replaced by L</build_metadata>. |
683ececb |
252 | |
253 | =cut |
254 | |
79b18b81 |
255 | method add_row_info (%opts) { |
256 | my ($row, $id, $info) = map { $opts{$_} } qw/row id info/; |
f1690863 |
257 | |
258 | warn 'DEPRECATED - add_row_info is deprecated in favour of build_metadata'; |
683ececb |
259 | if ($row) { |
260 | $id = $self->_mk_id(row => { $row->get_columns }); |
261 | } |
2aec43ca |
262 | |
263 | unless ($row || $self->find($id)) { |
683ececb |
264 | die 'invalid id passed to add_row_info'; |
265 | } |
266 | |
267 | if (my $existing = $self->_row_info->{$id}) { |
268 | $info = { %{$existing}, %{$info} }; |
269 | } |
270 | |
271 | $self->_row_info->{$id} = $info; |
b8e6d226 |
272 | } |
273 | |
f1690863 |
274 | # DEPRECATED |
79b18b81 |
275 | method row_info_for (%opts) { |
276 | my $id = $opts{id}; |
683ececb |
277 | return $self->_row_info->{$id}; |
b8e6d226 |
278 | } |
279 | |
f1690863 |
280 | # DEPRECATED |
79b18b81 |
281 | method _mk_id (%opts) { |
282 | my $row = $opts{row}; |
683ececb |
283 | return join('-', map { $row->{$_} } @{$self->id_cols}); |
b51d39c8 |
284 | } |
b8e6d226 |
285 | |
024c1044 |
286 | =head1 AUTHOR |
287 | |
288 | Luke Saunders <luke.saunders@gmail.com> |
289 | |
290 | =head1 THANKS |
291 | |
292 | As usual, thanks to Matt S Trout for the sanity check. |
293 | |
294 | =head1 LICENSE |
295 | |
296 | This library is free software under the same license as perl itself |
297 | |
298 | =cut |
299 | |
b8e6d226 |
300 | 1; |