File Coverage

blib/lib/Catmandu/Fix/lookup_in_store.pm
Criterion Covered Total %
statement 47 47 100.0
branch 11 12 91.6
condition 6 9 66.6
subroutine 13 13 100.0
pod n/a
total 77 81 95.0


line stmt bran cond sub pod time code
1              
2             use Catmandu::Sane;
3 1     1   98333  
  1         3  
  1         6  
4             our $VERSION = '1.2018';
5              
6             use Catmandu;
7 1     1   396 use Catmandu::Util::Path qw(as_path);
  1         3  
  1         4  
8 1     1   556 use Catmandu::Util qw(is_value);
  1         3  
  1         51  
9 1     1   6 use Moo;
  1         2  
  1         33  
10 1     1   4 use namespace::clean;
  1         2  
  1         4  
11 1     1   280 use Catmandu::Fix::Has;
  1         1  
  1         4  
12 1     1   621  
  1         2  
  1         6  
13             with 'Catmandu::Fix::Builder';
14              
15             has path => (fix_arg => 1);
16             has store_name => (fix_arg => 1);
17             has bag_name => (fix_opt => 1, init_arg => 'bag');
18             has default => (fix_opt => 1, predicate => 1);
19             has delete => (fix_opt => 1);
20             has store_args => (fix_opt => 'collect');
21             has store => (is => 'lazy', init_arg => undef);
22             has bag => (is => 'lazy', init_arg => undef);
23              
24             my ($self) = @_;
25             Catmandu->store($self->store_name, %{$self->store_args});
26 6     6   37 }
27 6         14  
  6         30  
28             my ($self) = @_;
29             defined $self->bag_name
30             ? $self->store->bag($self->bag_name)
31 6     6   41 : $self->store->bag;
32 6 50       85 }
33              
34             my ($self) = @_;
35              
36             my $bag = $self->bag;
37             my $cb;
38 6     6   42  
39             if ($self->delete) {
40 6         75 $cb = sub {
41 6         10 my $val = $_[0];
42             if (is_value($val) && defined($val = $bag->get($val))) {
43 6 100       21 return $val;
    100          
44             }
45 3     3   6 return undef, 1, 1;
46 3 100 66     51 };
47 1         16 }
48             elsif ($self->has_default) {
49 2         45 my $default = $self->default;
50 2         8 $cb = sub {
51             my $val = $_[0];
52             if (is_value($val) && defined($val = $bag->get($val))) {
53 2         6 return $val;
54             }
55 3     3   4 $default;
56 3 100 66     53 };
57 1         17 }
58             else {
59 2         44 $cb = sub {
60 2         9 my $val = $_[0];
61             if (is_value($val) && defined($val = $bag->get($val))) {
62             return $val;
63             }
64 2     2   8 return undef, 1, 0;
65 2 100 66     43 };
66 1         16 }
67              
68 1         22 as_path($self->path)->updater($cb);
69 2         19 }
70              
71             1;
72 6         29  
73              
74             =pod
75              
76             =head1 NAME
77              
78             Catmandu::Fix::lookup_in_store - change the value of a HASH key or ARRAY index
79             by looking up its value in a store
80              
81             =head1 SYNOPSIS
82              
83             # Lookup in an SQLLite database
84             lookup_in_store(foo.bar, DBI, data_source: "dbi:SQLite:path/data.sqlite")
85              
86             # Lookup in a MongoDB database
87             lookup_in_store(foo.bar, MongoDB, database_name: lookups, bag: mydata)
88              
89             # Lookup in a MongoDB database, using the default bag and a default value when nothing found
90             lookup_in_store(foo.bar, MongoDB, database_name: lookups, default: 'default value')
91              
92             # Lookup in a MongoDB database, using the default bag and delete the foo.bar field when nothing found
93             lookup_in_store(foo.bar, MongoDB, database_name: lookups, delete: 1)
94              
95             # Or, a much faster option: use a named store in a catmandu.yml file
96             #
97             # store:
98             # mydbi:
99             # package: DBI
100             # options:
101             # data_source: "dbi:SQLite:path/data.sqlite"
102             # mymongo:
103             # package: MongoDB
104             # options:
105             # database_name: lookups
106             lookup_in_store(foo.bar, mydbi)
107             lookup_in_store(foo.bar, mymongo, bag: mydata)
108             lookup_in_store(foo.bar, mymongo, default: 'default value')
109             lookup_in_store(foo.bar, mymongo, delete: 1)
110              
111             =head1 DESCRIPTION
112              
113             =head2 lookup_in_store(PATH,STORE[,store_param: store_val, ...][,bag: bag_name][,delete:1][,default:value])
114              
115             Use the lookup_in_store fix to match a field in a record to the "_id" field in
116             a Catmandu::Store of choice. For instance, if a Catmandu::Store contains these
117             records:
118              
119             ---
120             _id: water
121             fr: l'eau
122             de: wasser
123             en: water
124             nl: water
125             ---
126             _id: tree
127             fr: arbre
128             de: baum
129             en: tree
130             nl: boom
131              
132             And you data contains these fields:
133              
134             ---
135             _id: 001
136             tag: tree
137             ---
138             _id: 002
139             tag: water
140              
141             Then, the fix below will lookup a tag in the Catmandu::Store and replace it
142             with the database value:
143              
144             lookup_in_store(tag, DBI, data_source: "dbi:SQLite:path/data.sqlite")
145              
146             The resulting data will contain:
147              
148             ---
149             _id: 001
150             tag:
151             _id: tree
152             fr: arbre
153             de: baum
154             en: tree
155             nl: boom
156             ---
157             _id: 002
158             tag:
159             _id: water
160             fr: l'eau
161             de: wasser
162             en: water
163             nl: water
164              
165             =head1 DATABASE CONNECTIONS
166              
167             For every call to a C<lookup_in_store> a new database connection is created. It
168             is much more effient to used named stores in a C<catmandu.yml> file. This file
169             needs to contain all the connection parameters to the database. E.g.
170              
171             store:
172             mystore:
173             package: MongoDB
174             options:
175             database_name: mydata
176              
177             The C<catmandu.yml> file should be available in the same directory as where the
178             C<catmandu> command is executed. Or, this directory can be set with the C<-L> option:
179              
180             $ catmandu -L /tmp/path convert ...
181              
182             =head1 SEE ALSO
183              
184             L<Catmandu::Fix>, L<Catmandu::Store> , L<Catmandu::Fix::add_to_store>
185              
186             =cut