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

            
added tests
Yuki Kimoto authored on 2011-08-26
4
use Carp 'croak';
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
5
use DBIx::Custom::Util '_subname';
6

            
7
# Carp trust relationship
8
push @DBIx::Custom::CARP_NOT, __PACKAGE__;
9

            
added tests
Yuki Kimoto authored on 2011-08-26
10
has [qw/param pass/],
11
    condition => sub {
12
        sub { defined $_[0] && length $_[0] }
13
    };
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
14

            
15
sub map {
16
    my ($self, %rule) = @_;
17
    my $param = $self->param;
18
    
19
    # Mapping
20
    my $new_param = {};
21
    foreach my $key (keys %$param) {
22
    
23
        my $value_cb;
24
        my $condition;
25
        my $new_key;
26
        
27
        # Get mapping information
28
        if (ref $rule{$key} eq 'ARRAY') {
29
            foreach my $some (@{$rule{$key}}) {
30
                $new_key = $some unless ref $some;
added tests
Yuki Kimoto authored on 2011-08-26
31
                $condition = $some->{condition} if ref $some eq 'HASH';
added DBIx::Custom::Mapper
Yuki Kimoto authored on 2011-08-26
32
                $value_cb = $some if ref $some eq 'CODE';
33
            }
34
        }
35
        elsif (defined $rule{$key}) {
36
            $new_key = $rule{$key};
37
        }
38
        else {
39
            $new_key = $key;
40
        }
41
        
42
        $value_cb ||= sub { $_[0] };
43
        $condition ||= $self->condition;
44
        $condition = $self->_condition_to_sub($condition);
45

            
46
        # Map parameter
47
        my $value;
48
        if (ref $condition eq 'CODE') {
49
            if (ref $param->{$key} eq 'ARRAY') {
50
                $new_param->{$new_key} = [];
51
                for (my $i = 0; $i < @{$param->{$key}}; $i++) {
52
                    $new_param->{$new_key}->[$i]
53
                      = $condition->($param->{$key}->[$i]) ? $param->{$key}->[$i]
54
                      : $self->dbi->not_exists;
55
                }
56
            }
57
            else {
58
                $new_param->{$new_key} = $value_cb->($param->{$key})
59
                  if $condition->($param->{$key});
60
            }
61
        }
62
        elsif ($condition eq 'exists') {
63
            if (ref $param->{$key} eq 'ARRAY') {
64
                $new_param->{$new_key} = [];
65
                for (my $i = 0; $i < @{$param->{$key}}; $i++) {
66
                    $new_param->{$new_key}->[$i]
67
                      = exists $param->{$key}->[$i] ? $param->{$key}->[$i]
68
                      : $self->dbi->not_exists;
69
                }
70
            }
71
            else {
72
                $new_param->{$new_key} = $value_cb->($param->{$key})
73
                  if exists $param->{$key};
74
            }
75
        }
76
        else { croak qq/Condition must be code reference or "exists" / . _subname }
77
    }
78
    
79
    return $new_param;
80
}
81

            
82
sub new {
83
    my $self = shift->SUPER::new(@_);
84
    
85
    # Check attribute names
86
    my @attrs = keys %$self;
87
    foreach my $attr (@attrs) {
88
        croak qq{"$attr" is invalid attribute name (} . _subname . ")"
89
          unless $self->can($attr);
90
    }
91
    
92
    return $self;
93
}
94

            
95

            
96
sub _condition_to_sub {
97
    my ($self, $if) = @_;
98
    $if = $if eq 'exists' ? $if
99
            : $if eq 'defined' ? sub { defined $_[0] }
100
            : $if eq 'length'  ? sub { defined $_[0] && length $_[0] }
101
            : ref $if eq 'CODE' ? $if
102
            : undef;
103

            
104
    croak "You can must specify right value to C<condition> " . _subname
105
      unless $if;
106
    
107
    return $if;
108
}
109

            
110
1;
111

            
112
=head1 NAME
113

            
114
DBIx::Custom::Mapper - Mapper of parameter EXPERIMENTAL
115

            
116
=head1 SYNOPSYS
117

            
118
    my $mapper = $dbi->mapper(param => $param);
119
    my $new_param = $mapper->map(
120
        title => 'book.title', # Key
121
        author => sub { '%' . $_[0] . '%'} # Value
122
        price => ['book.price' => sub { '%' . $_[0] . '%' }], # Key and value
123
    );
124

            
125
=head1 ATTRIBUTES
126

            
127
=head2 C<param>
128

            
129
    my $param = $mapper->param;
130
    $mapper = $mapper->param({title => 'Perl', author => 'Ken'});
131

            
132
Parameter.
133

            
134
=head2 C<ignore>
135

            
136
    my $pass = $mapper->ignore;
137
    $mapper = $mapper->ignore([qw/title author/]);
138

            
139
Ignored parameter keys when C<map> method is executed.
140

            
141
=head2 C<condition>
142

            
143
    my $condition = $mapper->condition;
144
    $mapper = $mapper->condition('exists');
145

            
146
Mapping condtion, default to C<length>.
147

            
148
You can set the following values to C<condition>.
149

            
150
=over 4
151

            
152
=item * C<exists>
153
   
154
    condition => 'exists'
155

            
156
If key exists, key and value is mapped.
157

            
158
=item * C<defined>
159

            
160
    condition => 'defined';
161

            
162
If value is defined, key and value is mapped.
163

            
164
=item * C<length>
165

            
166
    condition => 'length';
167

            
168
If value is defined and has length, key and value is mapped.
169

            
170
=item * C<code reference>
171

            
172
    condition => sub { defined $_[0] }
173

            
174
You can set code reference to C<condtion>.
175
The subroutine return true, key and value is mapped.
176

            
177
=head1 METHODS
178

            
179
L<DBIx::Custom::Mapper> inherits all methods from L<Object::Simple>
180
and implements the following new ones.
181

            
182
=head2 C<map>
183

            
184
    my $new_param = $mapper->map(
185
        price => 'book.price', # Key
186
        title => sub { '%' . $_[0] . '%'}, # Value
187
        author => ['book.author', sub { '%' . $_[0] . '%'}] # Key and value
188
    );
189

            
190
Map C<param>'s key and value and return new parameter.
191

            
192
For example, if C<param> is set to
193

            
194
    {
195
        price => 1900,
196
        title => 'Perl',
197
        author => 'Ken',
198
        issue_date => '2010-11-11'
199
    }
200

            
201
The following hash reference is returned.
202

            
203
    {
204
        'book.price' => 1900,
205
        title => '%Perl%',
206
        'book.author' => '%Ken%',
207
        issude_date => '2010-11-11'
208
    }
209

            
210
By default, If the value has length, key and value is mapped.
211

            
212
    title => 'Perl'  # Mapped
213
    {title => '' }   # Not mapped
214
    {title => undef} # Not mapped
215
    {}               # Not mapped
216

            
217
You can set change mapping condition by C<condition> attribute.
218

            
219
    $mapper->condition('defined');
220

            
221
Or you can set C<condtion> option for each key.
222

            
223
    my $new_param = $mapper->map(
224
        price => ['book.price', {condition => 'defined'}]
225
        title => [sub { '%' . $_[0] . '%'}, {condition => 'defined'}] # Value
226
        author => ['book.author', sub { '%' . $_[0] . '%'}, condtion => 'exists']
227
    );
228

            
229
If C<ignore> is set, the keys is ignored.
230

            
231
    $mapper->ignore([qw/title author/]);
232
    
233
    {title => 'Perl', author => 'Ken', price => 1900}
234
      is mapped to {price => 1900}
235

            
236
=cut