optimsation to avoid unnecessary finds
[dbsrgits/DBIx-Class-ResultSet-WithMetaData.git] / lib / DBIx / Class / ResultSet / WithMetaData.pm
CommitLineData
b8e6d226 1package DBIx::Class::ResultSet::WithMetaData;
2
3use strict;
4use warnings;
5
6use Data::Alias;
7use Moose;
79b18b81 8use Method::Signatures::Simple;
b8e6d226 9extends 'DBIx::Class::ResultSet';
10
11has '_row_info' => (
683ececb 12 is => 'rw',
13 isa => 'HashRef'
b8e6d226 14);
15
16has 'was_row' => (
683ececb 17 is => 'rw',
18 isa => 'Int'
b8e6d226 19);
20
b51d39c8 21has 'id_cols' => (
683ececb 22 is => 'rw',
23 isa => 'ArrayRef',
b51d39c8 24);
683ececb 25
26=head1 VERSION
27
28Version 0.999001
29
30=cut
31
32our $VERSION = '0.999001';
33
34=head1 NAME
35
36DBIx::Class::ResultSet::WithMetaData
37
38=head1 SYNOPSIS
39
40 package MyApp::Schema::ResultSet::ObjectType;
41
42 use Moose;
43 use MooseX::Method::Signatures;
44 extends 'DBIx::Class::ResultSet::WithMetaData;
45
46 method with_substr () {
47 foreach my $row ($self->all) {
48 my $substr = substr($row->name, 0, 3);
49 $self->add_row_info(row => $row, info => { substr => $substr });
50 }
51 return $self;
52 }
53
54 ...
55
56
57 # then somewhere else
58
59 my $object_type_arrayref = $object_type_rs->limit(count => 3)->with_substr->display();
60
61 # [{
62 # 'artistid' => '1',
63 # 'name' => 'Caterwauler McCrae',
64 # 'substr' => 'Cat'
65 # },
66 # {
67 # 'artistid' => '2',
68 # 'name' => 'Random Boy Band',
69 # 'substr' => 'Ran'
70 # },
71 # {
72 # 'artistid' => '3',
73 # 'name' => 'We Are Goth',
74 # 'substr' => 'We '
75 # }]
76
77=head1 DESCRIPTION
78
79Attach metadata to rows by chaining ResultSet methods together. When the ResultSet is
80flattened to an ArrayRef the attached metadata is merged with the row hashes to give
81a combined 'hash-plus-other-stuff' representation.
82
83=head1 METHODS
84
85=cut
b51d39c8 86
b8e6d226 87sub new {
683ececb 88 my $self = shift;
b51d39c8 89
683ececb 90 my $new = $self->next::method(@_);
91 foreach my $key (qw/_row_info was_row id_cols/) {
92 alias $new->{$key} = $new->{attrs}{$key};
93 }
b8e6d226 94
683ececb 95 unless ($new->_row_info) {
96 $new->_row_info({});
97 }
b8e6d226 98
683ececb 99 unless ($new->id_cols && scalar(@{$new->id_cols})) {
100 $new->id_cols([sort $new->result_source->primary_columns]);
101 }
b8e6d226 102
683ececb 103 return $new;
b8e6d226 104}
105
683ececb 106=head2 display
107
108=over 4
109
110=item Arguments: none
111
112=item Return Value: ArrayRef
113
114=back
115
116 $arrayref_of_row_hashrefs = $rs->display();
117
118This method uses L<DBIx::Class::ResultClass::HashRefInflator> to convert all
119rows in the ResultSet to HashRefs. These are then merged with any metadata
120that had been attached to the rows using L</add_row_info>.
121
122=cut
123
b8e6d226 124method display () {
125 my $rs = $self->search({});
126 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
127 my @rows;
683ececb 128 foreach my $row ($rs->all) {
129 if (my $info = $self->row_info_for(id => $self->_mk_id(row => $row))) {
130 $row = { %{$row}, %{$info} };
131 }
132 push(@rows, $row);
133 }
b8e6d226 134
135 return ($self->was_row) ? $rows[0] : \@rows;
136}
137
683ececb 138=head2 add_row_info
139
140=over 4
141
142=item Arguments: row => DBIx::Class::Row object, info => HashRef to attach to the row
143
144=item Return Value: ResultSet
145
146=back
147
148 $rs = $rs->add_row_info(row => $row, info => { dates => [qw/mon weds fri/] } );
149
150This method allows you to attach a HashRef of metadata to a row which will be merged
151with that row when the ResultSet is flattened to a datastructure with L</display>.
152
153=cut
154
79b18b81 155method add_row_info (%opts) {
156 my ($row, $id, $info) = map { $opts{$_} } qw/row id info/;
683ececb 157 if ($row) {
158 $id = $self->_mk_id(row => { $row->get_columns });
159 }
2aec43ca 160
161 unless ($row || $self->find($id)) {
683ececb 162 die 'invalid id passed to add_row_info';
163 }
164
165 if (my $existing = $self->_row_info->{$id}) {
166 $info = { %{$existing}, %{$info} };
167 }
168
169 $self->_row_info->{$id} = $info;
b8e6d226 170}
171
79b18b81 172method row_info_for (%opts) {
173 my $id = $opts{id};
683ececb 174 return $self->_row_info->{$id};
b8e6d226 175}
176
683ececb 177=head2 order_by (EXPERIMENTAL)
178
179=over 4
180
181=item Arguments: col => $column_name
182
183=item Return Value: ResultSet
184
185=back
186
187 $ordered_rs = $rs->order_by(col => 'name');
188
189Convenience method. Essentually a shortcut for $rs->search({}, { order_by => $col }).
190
191=cut
192
79b18b81 193method order_by (%opts) {
194 my $col = $opts{col};
683ececb 195 $col = "me.$col" unless ($col =~ m/\./);
196 return $self->search({}, { order_by => $col });
b8e6d226 197}
198
683ececb 199=head2 limit (EXPERIMENTAL)
200
201=over 4
202
203=item Arguments: count => Int
204
205=item Return Value: ResultSet
206
207=back
208
209 $limitted_rs = $rs->limit(count => 3);
210
211Convenience method. Essentually a shortcut for $rs->search({}, { rows => $count }).
212
213=cut
214
79b18b81 215method limit (%opts) {
216 my $count = $opts{count};
683ececb 217 return $self->search({}, { rows => $count });
b8e6d226 218}
219
79b18b81 220method _mk_id (%opts) {
221 my $row = $opts{row};
683ececb 222 return join('-', map { $row->{$_} } @{$self->id_cols});
b51d39c8 223}
b8e6d226 224
024c1044 225=head1 AUTHOR
226
227 Luke Saunders <luke.saunders@gmail.com>
228
229=head1 THANKS
230
231As usual, thanks to Matt S Trout for the sanity check.
232
233=head1 LICENSE
234
235 This library is free software under the same license as perl itself
236
237=cut
238
b8e6d226 2391;