Newer Older
259 lines | 6.803kb
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::Mapper
Yuki Kimoto authored on 2011-08-26
7
use DBIx::Custom::Util '_subname';
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/],
added tests
Yuki Kimoto authored on 2011-08-26
13
    condition => sub {
14
        sub { defined $_[0] && length $_[0] }
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
15
    },
16
    pass => sub { [] };
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
17

            
18
sub map {
19
    my ($self, %rule) = @_;
20
    my $param = $self->param;
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
21
    $rule{$_} = {key => $_} for @{$self->pass};
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
22
    
23
    # Mapping
24
    my $new_param = {};
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
25
    foreach my $key (keys %rule) {
26
        
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
27
        my $mapping = $rule{$key};
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
28
        
29
        # Get mapping information
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
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 = $mapping->[2];
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
38
        }
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
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;
46
            warn qq/map method's string value "$mapping" is DEPRECATED. / .
47
                 qq/use {key => ...} syntax instead/
48
        }
49
        elsif (ref $mapping eq 'CODE') {
50
            $value = $mapping;
51
            warn qq/map method's code reference value "$mapping" is DEPRECATED. / .
52
                 qq/use {value => ...} syntax instead/
53
        }
54
        
- added {KEY => {OPTION_KEY ...
Yuki Kimoto authored on 2011-09-02
55
        $new_key = $key unless defined $new_key;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
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]
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
66
                      : DBIx::Custom::NotExists->singleton;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
67
                }
68
            }
69
            else {
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
70
              if ($condition->($param->{$key})) {
71
                  $new_param->{$new_key} = defined $value
72
                                         ? $value->($param->{$key})
73
                                         : $param->{$key};
74
              }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
75
            }
76
        }
77
        elsif ($condition eq 'exists') {
78
            if (ref $param->{$key} eq 'ARRAY') {
79
                $new_param->{$new_key} = [];
80
                for (my $i = 0; $i < @{$param->{$key}}; $i++) {
81
                    $new_param->{$new_key}->[$i]
82
                      = exists $param->{$key}->[$i] ? $param->{$key}->[$i]
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
83
                      : DBIx::Custom::NotExists->singleton;
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
84
                }
85
            }
86
            else {
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
87
                if (exists $param->{$key}) {
88
                    $new_param->{$new_key} = defined $value
89
                                           ? $value->($param->{$key})
90
                                           : $param->{$key};
91
                }
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
92
            }
93
        }
94
        else { croak qq/Condition must be code reference or "exists" / . _subname }
95
    }
96
    
97
    return $new_param;
98
}
99

            
100
sub new {
101
    my $self = shift->SUPER::new(@_);
102
    
103
    # Check attribute names
104
    my @attrs = keys %$self;
105
    foreach my $attr (@attrs) {
106
        croak qq{"$attr" is invalid attribute name (} . _subname . ")"
107
          unless $self->can($attr);
108
    }
109
    
110
    return $self;
111
}
112

            
113

            
114
sub _condition_to_sub {
115
    my ($self, $if) = @_;
116
    $if = $if eq 'exists' ? $if
117
            : $if eq 'defined' ? sub { defined $_[0] }
118
            : $if eq 'length'  ? sub { defined $_[0] && length $_[0] }
119
            : ref $if eq 'CODE' ? $if
120
            : undef;
121

            
122
    croak "You can must specify right value to C<condition> " . _subname
123
      unless $if;
124
    
125
    return $if;
126
}
127

            
128
1;
129

            
130
=head1 NAME
131

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

            
134
=head1 SYNOPSYS
135

            
136
    my $mapper = $dbi->mapper(param => $param);
137
    my $new_param = $mapper->map(
138
        title => 'book.title', # Key
139
        author => sub { '%' . $_[0] . '%'} # Value
140
        price => ['book.price' => sub { '%' . $_[0] . '%' }], # Key and value
141
    );
142

            
143
=head1 ATTRIBUTES
144

            
145
=head2 C<param>
146

            
147
    my $param = $mapper->param;
148
    $mapper = $mapper->param({title => 'Perl', author => 'Ken'});
149

            
150
Parameter.
151

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

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
154
    my $pass = $mapper->pass;
155
    $mapper = $mapper->pass([qw/title author/]);
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
156

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
157
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
158

            
159
=head2 C<condition>
160

            
161
    my $condition = $mapper->condition;
162
    $mapper = $mapper->condition('exists');
163

            
164
Mapping condtion, default to C<length>.
165

            
166
You can set the following values to C<condition>.
167

            
168
=over 4
169

            
170
=item * C<exists>
171
   
172
    condition => 'exists'
173

            
174
If key exists, key and value is mapped.
175

            
176
=item * C<defined>
177

            
178
    condition => 'defined';
179

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

            
182
=item * C<length>
183

            
184
    condition => 'length';
185

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

            
188
=item * C<code reference>
189

            
190
    condition => sub { defined $_[0] }
191

            
192
You can set code reference to C<condtion>.
193
The subroutine return true, key and value is mapped.
194

            
195
=head1 METHODS
196

            
197
L<DBIx::Custom::Mapper> inherits all methods from L<Object::Simple>
198
and implements the following new ones.
199

            
200
=head2 C<map>
201

            
202
    my $new_param = $mapper->map(
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
203
        price => {key => 'book.price'}
204
        title => {value => sub { '%' . $_[0] . '%'}}
205
        author => ['book.author' => sub { '%' . $_[0] . '%'}] # Key and value
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
206
    );
207

            
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
208
Map C<param> into new parameter.
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
209

            
210
For example, if C<param> is set to
211

            
212
    {
213
        price => 1900,
214
        title => 'Perl',
215
        author => 'Ken',
216
        issue_date => '2010-11-11'
217
    }
218

            
219
The following hash reference is returned.
220

            
221
    {
222
        'book.price' => 1900,
223
        title => '%Perl%',
224
        'book.author' => '%Ken%',
225
    }
226

            
227
By default, If the value has length, key and value is mapped.
228

            
229
    title => 'Perl'  # Mapped
230
    {title => '' }   # Not mapped
231
    {title => undef} # Not mapped
232
    {}               # Not mapped
233

            
234
You can set change mapping condition by C<condition> attribute.
235

            
236
    $mapper->condition('defined');
237

            
238
Or you can set C<condtion> option for each key.
239

            
240
    my $new_param = $mapper->map(
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
241
        price => {key => 'book.price', condition => 'defined'}]
242
        title => {value => sub { '%' . $_[0] . '%'}, condition => 'defined'}
243
        author => ['book.author', sub { '%' . $_[0] . '%'}, 'exists']
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
244
    );
245

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
246
If C<pass> attrivute is set, the keys and value is copied without change.
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
247

            
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
248
    $mapper->pass([qw/title author/]);
- added {key => ..., value =...
Yuki Kimoto authored on 2011-10-04
249
    my $new_param = $mapper->map(price => {key => 'book.price'});
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
250

            
251
The following hash reference
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
252
    
253
    {title => 'Perl', author => 'Ken', price => 1900}
- added EXPERIMENTAL pass at...
Yuki Kimoto authored on 2011-09-02
254

            
255
is mapped to
256

            
257
    {title => 'Perl', author => 'Ken', 'book.price' => 1900}
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
258

            
259
=cut