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; |
8 | use MooseX::Method::Signatures; |
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 | |
26 | =head1 VERSION |
27 | |
28 | Version 0.999001 |
29 | |
30 | =cut |
31 | |
32 | our $VERSION = '0.999001'; |
33 | |
34 | =head1 NAME |
35 | |
36 | DBIx::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 | |
79 | Attach metadata to rows by chaining ResultSet methods together. When the ResultSet is |
80 | flattened to an ArrayRef the attached metadata is merged with the row hashes to give |
81 | a combined 'hash-plus-other-stuff' representation. |
82 | |
83 | =head1 METHODS |
84 | |
85 | =cut |
b51d39c8 |
86 | |
b8e6d226 |
87 | sub 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 | |
118 | This method uses L<DBIx::Class::ResultClass::HashRefInflator> to convert all |
119 | rows in the ResultSet to HashRefs. These are then merged with any metadata |
120 | that had been attached to the rows using L</add_row_info>. |
121 | |
122 | =cut |
123 | |
b8e6d226 |
124 | method 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 | |
150 | This method allows you to attach a HashRef of metadata to a row which will be merged |
151 | with that row when the ResultSet is flattened to a datastructure with L</display>. |
152 | |
153 | =cut |
154 | |
46845551 |
155 | method 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 | |
170 | method 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 | |
186 | Convenience method. Essentually a shortcut for $rs->search({}, { order_by => $col }). |
187 | |
188 | =cut |
189 | |
b8e6d226 |
190 | method 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 | |
207 | Convenience method. Essentually a shortcut for $rs->search({}, { rows => $count }). |
208 | |
209 | =cut |
210 | |
b8e6d226 |
211 | method limit (Int :$count) { |
683ececb |
212 | return $self->search({}, { rows => $count }); |
b8e6d226 |
213 | } |
214 | |
b51d39c8 |
215 | method _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 | |
225 | As 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 |
233 | 1; |