Newer Older
318 lines | 7.522kb
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
1
package DBIx::Custom::Mapper;
2
use Object::Simple -base;
3

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
4
use DBIx::Custom::NotExists;
5

            
added tests
Yuki Kimoto authored on 2011-08-26
6
use Carp 'croak';
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
7
use DBIx::Custom::Util qw/_subname _deprecate/;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
8

            
9
# Carp trust relationship
10
push @DBIx::Custom::CARP_NOT, __PACKAGE__;
11

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
12
has [qw/param/],
cleanup
Yuki Kimoto authored on 2012-01-20
13
  condition => sub {
14
    sub { defined $_[0] && length $_[0] }
15
  },
16
  pass => sub { [] };
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
17

            
18
sub map {
cleanup
Yuki Kimoto authored on 2012-01-20
19
  my ($self, %rule) = @_;
20
  my $param = $self->param;
21
  $rule{$_} = {key => $_} for @{$self->pass};
22
  
23
  # Mapping
24
  my $new_param = {};
25
  for my $key (keys %rule) {
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
26
    
cleanup
Yuki Kimoto authored on 2012-01-20
27
    my $mapping = $rule{$key};
28
    
29
    # Get mapping information
30
    my $new_key;
31
    my $value;
32
    my $condition;
33
    
34
    if (ref $mapping eq 'ARRAY') {
35
      $new_key = $mapping->[0];
36
      $value = $mapping->[1];
37
      $condition = ref $mapping->[2] eq 'HASH' ? $mapping->[2]->{condition} : $mapping->[2];
38
    }
39
    elsif (ref $mapping eq 'HASH') {
40
      $new_key = $mapping->{key};
41
      $value = $mapping->{value};
42
      $condition = $mapping->{condition};
43
    }
44
    elsif (!ref $mapping) {
45
      $new_key = $mapping;
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
46
      _deprecate('0.24', qq/map method's string value "$mapping" is DEPRECATED. / .
47
        qq/use {key => ...} syntax instead/);
cleanup
Yuki Kimoto authored on 2012-01-20
48
    }
49
    elsif (ref $mapping eq 'CODE') {
50
      $value = $mapping;
- added DBIX_CUSTOM_SUPPRESS...
Yuki Kimoto authored on 2012-03-19
51
      _deprecate('0.24', qq/map method's code reference value "$mapping" is DEPRECATED. / .
52
        qq/use {value => ...} syntax instead/);
cleanup
Yuki Kimoto authored on 2012-01-20
53
    }
54
    
55
    $new_key = $key unless defined $new_key;
56
    $condition ||= $self->condition;
57
    $condition = $self->_condition_to_sub($condition);
58

            
59
    # Map parameter
60
    if (ref $condition eq 'CODE') {
61
      if (ref $param->{$key} eq 'ARRAY') {
62
        $new_param->{$new_key} = [];
63
        for (my $i = 0; $i < @{$param->{$key}}; $i++) {
64
          $new_param->{$new_key}->[$i]
65
            = $condition->($param->{$key}->[$i]) ? $param->{$key}->[$i]
66
            : DBIx::Custom::NotExists->singleton;
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
67
        }
cleanup
Yuki Kimoto authored on 2012-01-20
68
      }
69
      else {
70
        if ($condition->($param->{$key})) {
- DBIx::Custom::Mapper::map ...
Yuki Kimoto authored on 2012-02-29
71
          if (defined $value) {
72
            if (ref $value) {
73
              $new_param->{$new_key} = $value->($param->{$key});
74
            }
75
            else {
76
              $value =~ s/<value>/$param->{$key}/e;
77
              $new_param->{$new_key} = $value;
78
            }
79
          }
80
          else { $new_param->{$new_key} = $param->{$key} }
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
81
        }
cleanup
Yuki Kimoto authored on 2012-01-20
82
      }
83
    }
84
    elsif ($condition eq 'exists') {
85
      if (ref $param->{$key} eq 'ARRAY') {
86
        $new_param->{$new_key} = [];
87
        for (my $i = 0; $i < @{$param->{$key}}; $i++) {
88
          $new_param->{$new_key}->[$i]
89
            = exists $param->{$key}->[$i] ? $param->{$key}->[$i]
90
            : DBIx::Custom::NotExists->singleton;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
91
        }
cleanup
Yuki Kimoto authored on 2012-01-20
92
      }
93
      else {
94
        if (exists $param->{$key}) {
95
          $new_param->{$new_key} = defined $value
96
            ? $value->($param->{$key}) : $param->{$key};
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
97
        }
cleanup
Yuki Kimoto authored on 2012-01-20
98
      }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
99
    }
cleanup
Yuki Kimoto authored on 2012-01-20
100
    else { croak qq/Condition must be code reference or "exists" / . _subname }
101
  }
102
  
103
  return $new_param;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
104
}
105

            
106
sub new {
cleanup
Yuki Kimoto authored on 2012-01-20
107
  my $self = shift->SUPER::new(@_);
108
  
109
  # Check attribute names
110
  my @attrs = keys %$self;
111
  for my $attr (@attrs) {
112
    croak qq{"$attr" is invalid attribute name (} . _subname . ")"
113
      unless $self->can($attr);
114
  }
115
  
116
  return $self;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
117
}
118

            
119

            
120
sub _condition_to_sub {
cleanup
Yuki Kimoto authored on 2012-01-20
121
  my ($self, $if) = @_;
122
  $if = $if eq 'exists' ? $if
123
    : $if eq 'defined' ? sub { defined $_[0] }
124
    : $if eq 'length'  ? sub { defined $_[0] && length $_[0] }
125
    : ref $if eq 'CODE' ? $if
126
    : undef;
127

            
128
  croak "You can must specify right value to C<condition> " . _subname
129
    unless $if;
130
  
131
  return $if;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
132
}
133

            
134
1;
135

            
136
=head1 NAME
137

            
sqlfilter option is renamed ...
Yuki Kimoto authored on 2011-09-16
138
DBIx::Custom::Mapper - Mapper of parameter
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
139

            
140
=head1 SYNOPSYS
141

            
cleanup
Yuki Kimoto authored on 2012-01-20
142
  my $mapper = $dbi->mapper(param => $param);
143
  my $new_param = $mapper->map(
144
    title => 'book.title', # Key
145
    author => sub { '%' . $_[0] . '%'} # Value
146
    price => ['book.price' => sub { '%' . $_[0] . '%' }], # Key and value
147
  );
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
148

            
149
=head1 ATTRIBUTES
150

            
151
=head2 C<param>
152

            
cleanup
Yuki Kimoto authored on 2012-01-20
153
  my $param = $mapper->param;
154
  $mapper = $mapper->param({title => 'Perl', author => 'Ken'});
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
155

            
156
Parameter.
157

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
158
=head2 C<pass>
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
159

            
cleanup
Yuki Kimoto authored on 2012-01-20
160
  my $pass = $mapper->pass;
161
  $mapper = $mapper->pass([qw/title author/]);
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
162

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
163
the key and value is copied without change when C<map> method is executed.
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
164

            
165
=head2 C<condition>
166

            
cleanup
Yuki Kimoto authored on 2012-01-20
167
  my $condition = $mapper->condition;
168
  $mapper = $mapper->condition('exists');
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
169

            
170
Mapping condtion, default to C<length>.
171

            
172
You can set the following values to C<condition>.
173

            
174
=over 4
175

            
176
=item * C<exists>
cleanup
Yuki Kimoto authored on 2012-01-20
177
 
178
  condition => 'exists'
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
179

            
180
If key exists, key and value is mapped.
181

            
182
=item * C<defined>
183

            
cleanup
Yuki Kimoto authored on 2012-01-20
184
  condition => 'defined';
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
185

            
186
If value is defined, key and value is mapped.
187

            
188
=item * C<length>
189

            
cleanup
Yuki Kimoto authored on 2012-01-20
190
  condition => 'length';
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
191

            
192
If value is defined and has length, key and value is mapped.
193

            
194
=item * C<code reference>
195

            
cleanup
Yuki Kimoto authored on 2012-01-20
196
  condition => sub { defined $_[0] }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
197

            
198
You can set code reference to C<condtion>.
199
The subroutine return true, key and value is mapped.
200

            
201
=head1 METHODS
202

            
203
L<DBIx::Custom::Mapper> inherits all methods from L<Object::Simple>
204
and implements the following new ones.
205

            
206
=head2 C<map>
207

            
cleanup
Yuki Kimoto authored on 2012-01-20
208
  my $new_param = $mapper->map(
209
    price => {key => 'book.price'}
- DBIx::Custom::Mapper::map ...
Yuki Kimoto authored on 2012-02-29
210
    title => {value => '%<value>%'}
211
    author => ['book.author' => '%<value>%']
212
  );
213

            
214
  my $new_param = $mapper->map(
215
    price => {key => 'book.price'}
216
    title => {value => sub { '%' . shift . '%'}}
217
    author => ['book.author' => sub { '%' . shift . '%'}]
cleanup
Yuki Kimoto authored on 2012-01-20
218
  );
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
219

            
- DBIx::Custom::Mapper::map ...
Yuki Kimoto authored on 2012-02-29
220
Map parameter in C<param> attribute into new parameter.
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
221

            
222
For example, if C<param> is set to
223

            
cleanup
Yuki Kimoto authored on 2012-01-20
224
  {
225
    price => 1900,
226
    title => 'Perl',
227
    author => 'Ken',
228
    issue_date => '2010-11-11'
229
  }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
230

            
231
The following hash reference is returned.
232

            
cleanup
Yuki Kimoto authored on 2012-01-20
233
  {
234
    'book.price' => 1900,
235
    title => '%Perl%',
236
    'book.author' => '%Ken%',
237
  }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
238

            
- DBIx::Custom::Mapper::map ...
Yuki Kimoto authored on 2012-02-29
239
=over 2
240

            
241
B<Syntax:>
242

            
243
=item * String => Hash reference
244

            
245
  # String => Hash reference
246
  price => {key => 'book.price'}
247
  title => {value => '%<value>%'}
248
  title => {value => sub { '%' . shift . '%'}}
249

            
250
If C<key> is used, only key name is mapped to new parameter
251

            
252
  # Rule
253
  price => {key => 'book.price'}
254
  # Parameter
255
  price => 1900,
256
  # New parameter
257
  'book.price' => 1900,
258

            
259
If C<value> is used, only value is mapped to new parameter
260

            
261
  # Rule
262
  title => {value => '%<value>%'}
263
  title => {value => sub { '%' . shift . '%'}}
264
  
265
  # Parameter
266
  title => 'Perl',
267
  # New parameter
268
  title => '%Perl%',
269

            
270
C<E<lt>>valueE<gt>> is replaced by original value.
271
You can use code reference to convert original value.
272

            
273
=item * String => Array reference
274
  
275
  # String => Array reference
276
  author => ['book.author' => '%<value>%']
277

            
278
Both key name name and value is mapped to new parameter.
279
This is same as the following syntax.
280

            
281
  # Rule
282
  {key => 'book.author', value => '%<value>%'}
283

            
284
=back
285

            
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
286
By default, If the value has length, key and value is mapped.
287

            
cleanup
Yuki Kimoto authored on 2012-01-20
288
  title => 'Perl'  # Mapped
289
  {title => '' }   # Not mapped
290
  {title => undef} # Not mapped
291
  {}               # Not mapped
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
292

            
293
You can set change mapping condition by C<condition> attribute.
294

            
cleanup
Yuki Kimoto authored on 2012-01-20
295
  $mapper->condition('defined');
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
296

            
297
Or you can set C<condtion> option for each key.
298

            
cleanup
Yuki Kimoto authored on 2012-01-20
299
  my $new_param = $mapper->map(
300
    price => {key => 'book.price', condition => 'defined'}]
301
    title => {value => sub { '%' . $_[0] . '%'}, condition => 'defined'}
302
    author => ['book.author', sub { '%' . $_[0] . '%'}, 'exists']
303
  );
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
304

            
- DBIx::Custom::Mapper::map ...
Yuki Kimoto authored on 2012-02-29
305
If C<pass> attribute is set, the keys and value is copied without change.
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
306

            
cleanup
Yuki Kimoto authored on 2012-01-20
307
  $mapper->pass([qw/title author/]);
308
  my $new_param = $mapper->map(price => {key => 'book.price'});
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
309

            
310
The following hash reference
cleanup
Yuki Kimoto authored on 2012-01-20
311
  
312
  {title => 'Perl', author => 'Ken', price => 1900}
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
313

            
314
is mapped to
315

            
cleanup
Yuki Kimoto authored on 2012-01-20
316
  {title => 'Perl', author => 'Ken', 'book.price' => 1900}
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
317

            
318
=cut