added contribs
[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;
8use MooseX::Method::Signatures;
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
46845551 155method add_row_info (Int :$id, :$row, HashRef :$info) {
683ececb 156 if ($row) {
157 $id = $self->_mk_id(row => { $row->get_columns });
158 }
159 unless ($self->find($id)) {
160 die 'invalid id passed to add_row_info';
161 }
162
163 if (my $existing = $self->_row_info->{$id}) {
164 $info = { %{$existing}, %{$info} };
165 }
166
167 $self->_row_info->{$id} = $info;
b8e6d226 168}
169
170method row_info_for (Int :$id) {
683ececb 171 return $self->_row_info->{$id};
b8e6d226 172}
173
683ececb 174=head2 order_by (EXPERIMENTAL)
175
176=over 4
177
178=item Arguments: col => $column_name
179
180=item Return Value: ResultSet
181
182=back
183
184 $ordered_rs = $rs->order_by(col => 'name');
185
186Convenience method. Essentually a shortcut for $rs->search({}, { order_by => $col }).
187
188=cut
189
b8e6d226 190method order_by (Str :$col) {
683ececb 191 $col = "me.$col" unless ($col =~ m/\./);
192 return $self->search({}, { order_by => $col });
b8e6d226 193}
194
683ececb 195=head2 limit (EXPERIMENTAL)
196
197=over 4
198
199=item Arguments: count => Int
200
201=item Return Value: ResultSet
202
203=back
204
205 $limitted_rs = $rs->limit(count => 3);
206
207Convenience method. Essentually a shortcut for $rs->search({}, { rows => $count }).
208
209=cut
210
b8e6d226 211method limit (Int :$count) {
683ececb 212 return $self->search({}, { rows => $count });
b8e6d226 213}
214
b51d39c8 215method _mk_id (HashRef :$row) {
683ececb 216 return join('-', map { $row->{$_} } @{$self->id_cols});
b51d39c8 217}
b8e6d226 218
024c1044 219=head1 AUTHOR
220
221 Luke Saunders <luke.saunders@gmail.com>
222
223=head1 THANKS
224
225As usual, thanks to Matt S Trout for the sanity check.
226
227=head1 LICENSE
228
229 This library is free software under the same license as perl itself
230
231=cut
232
b8e6d226 2331;