File Coverage

blib/lib/Catmandu/Fix/lookup.pm
Criterion Covered Total %
statement 40 40 100.0
branch 6 6 100.0
condition 2 3 66.6
subroutine 11 11 100.0
pod n/a
total 59 60 98.3


line stmt bran cond sub pod time code
1             package Catmandu::Fix::lookup;
2              
3 1     1   106361 use Catmandu::Sane;
  1         3  
  1         6  
4              
5             our $VERSION = '1.2020';
6              
7 1     1   469 use Catmandu::Importer::CSV;
  1         5  
  1         48  
8 1     1   7 use Catmandu::Util::Path qw(as_path);
  1         2  
  1         57  
9 1     1   6 use Catmandu::Util qw(is_value);
  1         2  
  1         39  
10 1     1   6 use Moo;
  1         2  
  1         4  
11 1     1   372 use namespace::clean;
  1         5  
  1         5  
12 1     1   832 use Catmandu::Fix::Has;
  1         3  
  1         8  
13              
14             with 'Catmandu::Fix::Builder';
15              
16             has path => (fix_arg => 1);
17             has file => (fix_arg => 1);
18             has default => (fix_opt => 1, predicate => 1);
19             has delete => (fix_opt => 1);
20             has csv_args => (fix_opt => 'collect');
21             has dictionary => (is => 'lazy', init_arg => undef);
22              
23             sub _build_dictionary {
24 7     7   55 my ($self) = @_;
25             Catmandu::Importer::CSV->new(
26 7         134 %{$self->csv_args},
27             file => $self->file,
28             header => 0,
29             fields => ['key', 'val'],
30             )->reduce(
31             {},
32             sub {
33 36     36   66 my ($dict, $pair) = @_;
34 36         89 $dict->{$pair->{key}} = $pair->{val};
35 36         139 $dict;
36             }
37 7         13 );
38             }
39              
40             sub _build_fixer {
41 7     7   60 my ($self) = @_;
42 7         28 my $path = as_path($self->path);
43 7         1323 my $dict = $self->dictionary;
44 7         31 my $has_default = $self->has_default;
45 7         17 my $default = $self->default;
46 7         14 my $delete = $self->delete;
47             $path->updater(
48             sub {
49 9     9   16 my $val = $_[0];
50 9 100 66     61 if (is_value($val) && defined(my $new_val = $dict->{$val})) {
    100          
    100          
51 4         81 return $new_val;
52             }
53             elsif ($delete) {
54 2         37 return undef, 1, 1;
55             }
56             elsif ($has_default) {
57 2         37 return $default;
58             }
59 1         18 return undef, 1, 0;
60             }
61 7         201 );
62             }
63              
64             1;
65              
66             __END__
67              
68             =pod
69              
70             =head1 NAME
71              
72             Catmandu::Fix::lookup - change the value of a HASH key or ARRAY index by
73             looking up its value in a dictionary
74              
75             =head1 SYNOPSIS
76              
77             # dictionary.csv
78             # id,planet
79             # 1,sun
80             # 2,earth
81             # 3,moon
82              
83             # values found in the dictionary.csv will be replaced
84             # {foo => {bar => 2}}
85             lookup(foo.bar, dictionary.csv)
86             # {foo => {bar => 'earth'}}
87              
88             # values not found will be kept
89             # {foo => {bar => 232}}
90             lookup(foo.bar, dictionary.csv)
91             # {foo => {bar => 232}}
92              
93             # in case you have a different seperator
94             lookup(foo.bar, dictionary.csv, sep_char: |)
95              
96             # delete value if the lookup fails:
97             lookup(foo.bar, dictionary.csv, delete: 1)
98              
99             # use a default value if the lookup fails:
100             lookup(foo.bar, dictionary.csv, default: 'default value')
101              
102             =head1 SEE ALSO
103              
104             L<Catmandu::Fix>, L<Catmandu::Fix::mapping>
105              
106             =cut