1 package DBIx::Class::ResultSet::WithMetaData;
8 use Method::Signatures::Simple;
9 extends 'DBIx::Class::ResultSet';
26 has '_hash_modifiers' => (
31 has '_key_modifiers' => (
36 has '_object_hash_modifiers' => (
41 has '_object_key_modifiers' => (
52 our $VERSION = '1.000002';
56 DBIx::Class::ResultSet::WithMetaData
60 package MyApp::Schema::ResultSet::ObjectType;
63 use MooseX::Method::Signatures;
64 extends 'DBIx::Class::ResultSet::WithMetaData;
66 method with_substr () {
67 return $self->_with_meta_key(
69 return substr(shift->{name}, 0, 3);
79 my $object_type_arrayref = $object_type_rs->with_substr->display();
83 # 'name' => 'Caterwauler McCrae',
88 # 'name' => 'Random Boy Band',
93 # 'name' => 'We Are Goth',
99 Attach metadata to rows by chaining ResultSet methods together. When the ResultSet is
100 flattened to an ArrayRef the metadata is merged with the row hashes to give
101 a combined 'hash-plus-other-stuff' representation.
110 my $new = $self->next::method(@_);
111 foreach my $key (qw/_row_info was_row id_cols _key_modifiers _hash_modifiers _object_key_modifiers _object_hash_modifiers/) {
112 alias $new->{$key} = $new->{attrs}{$key};
115 unless ($new->_row_info) {
119 unless ($new->_key_modifiers) {
120 $new->_key_modifiers([]);
122 unless ($new->_hash_modifiers) {
123 $new->_hash_modifiers([]);
125 unless ($new->_object_key_modifiers) {
126 $new->_object_key_modifiers([]);
128 unless ($new->_object_hash_modifiers) {
129 $new->_object_hash_modifiers([]);
132 unless ($new->id_cols && scalar(@{$new->id_cols})) {
133 $new->id_cols([sort $new->result_source->primary_columns]);
143 =item Arguments: none
145 =item Return Value: ArrayRef
149 $arrayref_of_row_hashrefs = $rs->display();
151 This method uses L<DBIx::Class::ResultClass::HashRefInflator> to convert all
152 rows in the ResultSet to HashRefs. Then the subrefs that were added via
153 L</_with_meta_key> or L</_with_meta_hash> are run for each row and the
154 resulting data merged with them.
159 my $rs = $self->search({});
160 # $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
161 $rs->result_class('DBIx::Class::WithMetaData::Inflator');
163 foreach my $row_rep ($rs->all) {
164 # the custom inflator inflates to a arrayref with two versions of the row in it - hash and obj
165 my ($row, $row_obj) = @{$row_rep};
166 # THIS BLOCK IS DEPRECATED
167 if (my $info = $self->row_info_for(id => $self->_mk_id(row => $row))) {
168 $row = { %{$row}, %{$info} };
171 foreach my $modifier (@{$rs->_hash_modifiers}) {
172 my $row_hash = $modifier->($row);
173 if (ref $row_hash ne 'HASH') {
174 die 'modifier subref (added via build_metadata) did not return hashref';
177 # simple merge for now, potentially needs to be more complex
178 $row->{$_} = $row_hash->{$_} for keys %{$row_hash};
181 foreach my $modifier (@{$rs->_object_hash_modifiers}) {
182 my $row_hash = $modifier->($row, $row_obj);
183 if (ref $row_hash ne 'HASH') {
184 die 'modifier subref (added via build_metadata) did not return hashref';
187 # simple merge for now, potentially needs to be more complex
188 $row->{$_} = $row_hash->{$_} for keys %{$row_hash};
191 foreach my $params (@{$rs->_key_modifiers}) {
192 my $modifier = $params->{modifier};
193 my $key = $params->{key};
195 if (my $val = $modifier->($row)) {
200 foreach my $params (@{$rs->_object_key_modifiers}) {
201 my $modifier = $params->{modifier};
202 my $key = $params->{key};
204 if (my $val = $modifier->($row, $row_obj)) {
211 return ($self->was_row) ? $rows[0] : \@rows;
214 =head2 _with_meta_key
218 =item Arguments: key_name => subref($row_hash)
220 =item Return Value: ResultSet
224 $self->_with_meta_key( substr => sub ($row) {
225 return substr(shift->{name}, 0, 3);
228 This method allows you populate a certain key for each row hash at L</display> time.
232 method _with_meta_key ($key, $modifier) {
233 my $rs = $self->search({});
235 die 'build_metadata called without key';
238 unless ($modifier && (ref $modifier eq 'CODE')) {
239 die 'build_metadata called without modifier param';
242 push( @{$rs->_key_modifiers}, { key => $key, modifier => $modifier });
246 =head2 _with_object_meta_key
250 =item Arguments: key_name => subref($row_hash, $row_obj)
252 =item Return Value: ResultSet
256 $self->_with_object_meta_key( substr => sub {
257 my ($row_hash, $row_obj) = @_;
258 return substr($row_obj->row_method, 0, 3);
261 The same as L</_with_meta_key> but the subref gets the row object
262 as well as the row hash. This should only be used when you need to
263 access row methods as it's slower to inflate objects.
267 method _with_object_meta_key ($key, $modifier) {
268 my $rs = $self->search({});
270 die '_with_object_meta_key called without key';
273 unless ($modifier && (ref $modifier eq 'CODE')) {
274 die '_with_object_meta_key called without modifier param';
277 push( @{$rs->_object_key_modifiers}, { key => $key, modifier => $modifier });
281 =head2 _with_meta_hash
285 =item Arguments: subref($row_hash)
287 =item Return Value: ResultSet
291 $self->_with_meta_hash( sub ($row) {
293 my $return_hash = { substr => substr($row->{name}, 0, 3), substr2 => substr($row->{name}, 0, 4) };
297 Use this method when you want to populate multiple keys of the hash at the same time. If you just want to
298 populate one key, use L</_with_meta_key>.
302 method _with_meta_hash ($modifier) {
303 my $rs = $self->search({});
304 unless ($modifier && (ref $modifier eq 'CODE')) {
305 die 'build_metadata called without modifier param';
308 push( @{$rs->_hash_modifiers}, $modifier );
312 =head2 _with_object_meta_hash
316 =item Arguments: subref($row_hash, $row_object)
318 =item Return Value: ResultSet
322 $self->_with_object_meta_hash( sub {
323 my ($row_hash, $row_object) = @_;
325 my $return_hash = { substr => substr($row_object->name, 0, 3), substr2 => substr($row_hash->{name}, 0, 4) };
329 Like L</_with_meta_hash> but the subref gets the row object
330 as well as the row hash. This should only be used when you need to
331 access row methods as it's slower to inflate objects.
335 method _with_object_meta_hash ($modifier) {
336 my $rs = $self->search({});
337 unless ($modifier && (ref $modifier eq 'CODE')) {
338 die 'build_metadata called without modifier param';
341 push( @{$rs->_object_hash_modifiers}, $modifier );
345 =head2 add_row_info (DEPRECATED)
349 =item Arguments: row => DBIx::Class::Row object, info => HashRef to attach to the row
351 =item Return Value: ResultSet
355 $rs = $rs->add_row_info(row => $row, info => { dates => [qw/mon weds fri/] } );
357 DEPRECATED - this method is quite slow as it requires that you iterate through
358 the resultset each time you want to add metadata. Replaced by L</build_metadata>.
362 method add_row_info (%opts) {
363 my ($row, $id, $info) = map { $opts{$_} } qw/row id info/;
365 warn 'DEPRECATED - add_row_info is deprecated in favour of build_metadata';
367 $id = $self->_mk_id(row => { $row->get_columns });
370 unless ($row || $self->find($id)) {
371 die 'invalid id passed to add_row_info';
374 if (my $existing = $self->_row_info->{$id}) {
375 $info = { %{$existing}, %{$info} };
378 $self->_row_info->{$id} = $info;
382 method row_info_for (%opts) {
384 return $self->_row_info->{$id};
388 method _mk_id (%opts) {
389 my $row = $opts{row};
390 return join('-', map { $row->{$_} } @{$self->id_cols});
395 Luke Saunders <luke.saunders@gmail.com>
399 As usual, thanks to Matt S Trout for the sanity check.
403 This library is free software under the same license as perl itself