File Coverage

blib/lib/Data/Transpose.pm
Criterion Covered Total %
statement 63 65 96.9
branch 12 14 85.7
condition n/a
subroutine 12 12 100.0
pod 4 4 100.0
total 91 95 95.7


line stmt bran cond sub pod time code
1             package Data::Transpose;
2              
3 7     7   114196 use 5.010001;
  7         26  
4 7     7   35 use strict;
  7         13  
  7         198  
5 7     7   37 use warnings;
  7         17  
  7         207  
6              
7 7     7   3234 use Data::Transpose::Field;
  7         21  
  7         231  
8 7     7   4527 use Data::Transpose::Group;
  7         22  
  7         242  
9              
10 7     7   49 use Moo;
  7         13  
  7         43  
11 7     7   2246 use MooX::Types::MooseLike::Base qw(:all);
  7         14  
  7         3010  
12 7     7   41 use namespace::clean;
  7         13  
  7         57  
13              
14             =head1 NAME
15              
16             Data::Transpose - iterate, filter and validate data, and transpose to
17             different field names
18              
19             =head1 DESCRIPTION
20              
21             Caters to your needs for manipulating data by different operations,
22             which are filtering records, iterating records, validating and
23             transposing to different field names.
24              
25             =head1 VERSION
26              
27             Version 0.0021
28              
29             =cut
30              
31             our $VERSION = '0.0021';
32              
33             =head1 SYNOPSIS
34              
35             use warnings;
36             use strict;
37            
38             use Data::Transpose::Prefix;
39             use Data::Dumper;
40            
41             my $data = {
42             first => 'John',
43             last => 'Doe',
44             foo => 'bar',
45             };
46            
47             my $dtp = Data::Transpose::Prefix->new(prefix => 'user.');
48             foreach my $needs_prefix ( qw(first last) ) {
49             $dtp->field( $needs_prefix );
50             }
51            
52             my $output = $dtp->transpose( $data );
53            
54             print Data::Dumper->Dump([$data, $output], [qw(data output)]);
55              
56             outputs:
57              
58             $data = {
59             'first' => 'John',
60             'last' => 'Doe',
61             'foo' => 'bar'
62             };
63             $output = {
64             'user.last' => 'Doe',
65             'user.first' => 'John',
66             'foo' => 'bar'
67             };
68              
69             =head1 REFERENCE
70              
71             =over 4
72              
73             =item Validator
74              
75             L
76              
77             =item Iterator
78              
79             L
80              
81             =back
82              
83             =head1 METHODS
84              
85             =head2 new
86              
87             Parameters for the constructor are:
88              
89             =over 4
90              
91             =item unknown
92              
93             Determines how to treat fields in the input hash
94             which are not known to the Data::Transpose object:
95              
96             =over 4
97              
98             =item fail
99              
100             The transpose operation fails.
101              
102             =item pass
103              
104             Unknown fields in the input hash appear in the output
105             hash. This is the default behaviour.
106              
107             =item skip
108              
109             Unknown fields in the input hash don't appear in
110             the output hash.
111              
112             =back
113              
114             This doesn't apply to the L method.
115              
116             =back
117              
118             =cut
119              
120             has unknown => (is => 'ro',
121             isa => sub {
122             my $unknown = $_[0];
123             my %permitted = (
124             fail => 1,
125             pass => 1,
126             skip => 1,
127             );
128             die "unknown accepts only " . join(' ', keys %permitted)
129             unless $permitted{$unknown};
130             },
131             default => sub { 'pass' });
132              
133             has _fields => (is => 'ro',
134             isa => ArrayRef[Object],
135             default => sub { [] },
136             );
137              
138              
139             =head2 field
140              
141             Add a new L object and return it:
142              
143             $tp->field('email');
144              
145             =cut
146              
147             sub field {
148 12     12 1 116 my ($self, $name) = @_;
149 12         18 my ($object);
150              
151 12         201 $object = Data::Transpose::Field->new(name => $name);
152              
153 12         1010 push @{$self->_fields}, $object;
  12         52  
154              
155 12         64 return $object;
156             }
157              
158             =head2 group
159              
160             Add a new L object and return it:
161              
162             $tp->group('fullname', $tp->field('firstname'), $tp->field('lastname'));
163              
164             =cut
165              
166             sub group {
167 4     4 1 11 my ($self, $name, @objects) = @_;
168            
169 4         68 my $object = Data::Transpose::Group->new(name => $name,
170             objects => \@objects);
171              
172 4         606 push @{$self->_fields}, $object;
  4         11  
173            
174 4         14 return $object;
175             }
176              
177             =head2 transpose
178              
179             Transposes input:
180              
181             $new_record = $tp->transpose($orig_record);
182              
183             =cut
184              
185             sub transpose {
186 16     16 1 1273 my ($self, $vref) = @_;
187 16         22 my ($weed_value, $fld_name, $new_name, %new_record, %status);
188              
189 16         84 $status{$_} = 1 for keys %$vref;
190              
191 16         30 for my $fld (@{$self->_fields}) {
  16         56  
192 24         435 $fld_name = $fld->name;
193              
194             # set value and apply operations
195 24 100       2814 if (exists $vref->{$fld_name}) {
196 16         72 $weed_value = $fld->value($vref->{$fld_name});
197             }
198             else {
199 8         33 $weed_value = $fld->value(undef);
200             }
201              
202 24 100       426 if ($new_name = $fld->target) {
203 13         84 $new_record{$new_name} = $weed_value;
204             }
205             else {
206 11         1094 $new_record{$fld_name} = $weed_value;
207             }
208              
209 24         56 delete $status{$fld_name};
210             }
211              
212 16 100       58 if (keys %status) {
213             # unknown fields
214 4 100       21 if ($self->unknown eq 'pass') {
    100          
215             # pass through unknown fields
216 2         5 for (keys %status) {
217 2         7 $new_record{$_} = $vref->{$_};
218             }
219             }
220             elsif ($self->unknown eq 'fail') {
221 1         13 die "Unknown fields in input: ", join(',', keys %status), '.';
222             }
223             }
224              
225 15         57 return \%new_record;
226             }
227              
228             =head2 transpose_object
229              
230             Transposes an object into a hash reference.
231              
232             =cut
233              
234             sub transpose_object {
235 3     3 1 1131 my ($self, $obj) = @_;
236 3         12 my ($weed_value, $fld_name, $new_name, %new_record, %status);
237              
238 3         6 for my $fld (@{$self->_fields}) {
  3         13  
239 3         81 $fld_name = $fld->name;
240              
241             # set value and apply operations
242 3 50       32 if ($obj->can($fld_name)) {
243 0         0 $weed_value = $fld->value($obj->$fld_name());
244             }
245             else {
246 3         12 $weed_value = $fld->value;
247             }
248              
249 3 50       29 if ($new_name = $fld->target) {
250 3         21 $new_record{$new_name} = $weed_value;
251             }
252             else {
253 0         0 $new_record{$fld_name} = $weed_value;
254             }
255             }
256              
257 3         10 return \%new_record;
258             }
259              
260             =head1 AUTHOR
261              
262             Stefan Hornburg (Racke), C<< >>
263              
264             =head1 BUGS
265              
266             Please report any bugs or feature requests at
267             L.
268             I will be notified, and then you'll
269             automatically be notified of progress on your bug as I make changes.
270              
271             =head1 SUPPORT
272              
273             You can find documentation for this module with the perldoc command.
274              
275             perldoc Data::Transpose
276              
277             You can also look for information at:
278              
279             =over 4
280              
281             =item * Github's issue tracker (report bugs here)
282              
283             L
284              
285             =item * AnnoCPAN: Annotated CPAN documentation
286              
287             L
288              
289             =item * CPAN Ratings
290              
291             L
292              
293             =item * Search CPAN
294              
295             L
296              
297             =back
298              
299              
300             =head1 ACKNOWLEDGEMENTS
301              
302             Todd Wade for mxcheck test failures fix (GH #5, #11)
303             and improvements to documentation (GH #12, #13).
304              
305             =head1 LICENSE AND COPYRIGHT
306              
307             Copyright 2012-2016 Stefan Hornburg (Racke).
308              
309             This program is free software; you can redistribute it and/or modify it
310             under the terms of either: the GNU General Public License as published
311             by the Free Software Foundation; or the Artistic License.
312              
313             See http://dev.perl.org/licenses/ for more information.
314              
315              
316             =cut
317              
318             1; # End of Data::Transpose