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