Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision f9f7b56e

Von Sven Schöling vor mehr als 13 Jahren hinzugefügt

  • ID f9f7b56eb62b165317bdf2253171ff09da7ae2ed
  • Vorgänger 8fba112b
  • Nachfolger 62add698

SL/Helper/Csv.pm: header_acc umbenannt in dispatch, Doku, check_header

Unterschiede anzeigen:

SL/Helper/Csv.pm
8 8
use Text::CSV;
9 9
use Params::Validate qw(:all);
10 10
use Rose::Object::MakeMethods::Generic scalar => [ qw(
11
   file encoding sep_char quote_char escape_char header header_acc class
11
   file encoding sep_char quote_char escape_char header dispatch class
12 12
   numberformat dateformat _io _csv _objects _parsed _data _errors
13 13
) ];
14 14

  
......
22 22
    quote_char    => { default => '"' },
23 23
    escape_char   => { default => '"' },
24 24
    header        => { type    => ARRAYREF, optional => 1 },
25
    header_acc    => { type    => HASHREF,  optional => 1 },
25
    dispatch      => { type    => HASHREF,  optional => 1 },
26 26
    file          => 1,
27 27
    encoding      => 0,
28 28
    class         => 0,
......
74 74
  @{ $_[0]->_errors }
75 75
}
76 76

  
77
sub check_header {
78
  $_[0]->_check_header;
79
}
80

  
77 81
# private stuff
78 82

  
79 83
sub _open_file {
......
96 100
  $self->header($header);
97 101
}
98 102

  
103
sub _check_header_for_class {
104
  my ($self, %params) = @_;
105
  my @errors;
106

  
107
  return unless $self->class;
108
  return $self->header;
109

  
110
  for my $method (@{ $self->header }) {
111
    next if $self->class->can($self->_real_method($method));
112

  
113
    push @errors, [
114
      $method,
115
      undef,
116
      "header field $method is not recognized",
117
      undef,
118
      0,
119
    ];
120
  }
121

  
122
  $self->_push_error(@errors);
123

  
124
  return ! @errors;
125
}
126

  
99 127
sub _parse_data {
100 128
  my ($self, %params) = @_;
101 129
  my (@data, @errors);
......
120 148
  }
121 149

  
122 150
  $self->_data(\@data);
123
  $self->_errors(\@errors);
151
  $self->_push_error(@errors);
124 152

  
125
  return if @errors;
126
  return \@data;
153
  return ! @errors;
127 154
}
128 155

  
129 156
sub _encode_layer {
......
141 168
  for my $line (@{ $self->_data }) {
142 169
    push @objs, $self->class->new(
143 170
      map {
144
        ($self->header_acc && $self->header_acc->{$_}) || $_ => $line->{$_}
171
        $self->_real_method($_) => $line->{$_}
145 172
      } grep { $_ } keys %$line
146 173
    );
147 174
  }
......
149 176
  $self->_objects(\@objs);
150 177
}
151 178

  
179
sub _real_method {
180
  my ($self, $arg) = @_;
181
  ($self->dispatch && $self->dispatch->{$arg}) || $arg;
182
}
183

  
152 184
sub _guess_encoding {
153 185
  # won't fix
154 186
  'utf-8';
155 187
}
156 188

  
189
sub _push_error {
190
  my ($self, @errors) = @_;
191
  my @new_errors = ($self->errors, @errors);
192
  $self->_errors(\@new_errors);
193
}
194

  
157 195

  
158 196
1;
159 197

  
......
175 213
    sep_char    => ',',     # default ';'
176 214
    quote_char  => ''',     # default '"'
177 215
    header      => [qw(id text sellprice word)] # see later
178
    header_acc  => { sellprice => 'sellprice_as_number' }
216
    dispatch    => { sellprice => 'sellprice_as_number' }
179 217
    class       => 'SL::DB::CsvLine',   # if present, map lines to this
180 218
  )
181 219

  
......
191 229
most cases you will want those line to be parsed into hashes or even objects,
192 230
so this model just skips ahead and gives you objects.
193 231

  
194
Encoding autodetection is not easy, and should not be trusted. Try to avoid it if possible.
232
Encoding autodetection is not easy, and should not be trusted. Try to avoid it
233
if possible.
195 234

  
196 235
=head1 METHODS
197 236

  
......
233 272

  
234 273
=item C<encoding>
235 274

  
236
Encoding of the CSV file. Note that this module does not do any encoding guessing.
237
Know what your data ist. Defaults to utf-8.
275
Encoding of the CSV file. Note that this module does not do any encoding
276
guessing.  Know what your data ist. Defaults to utf-8.
238 277

  
239 278
=item C<sep_char>
240 279

  
......
246 285

  
247 286
=item C<header> \@FIELDS
248 287

  
249
can be an array of columns, in this case the first line is not used as a
288
Can be an array of columns, in this case the first line is not used as a
250 289
header. Empty header fields will be ignored in objects.
251 290

  
252
=item C<header_acc> \%ACCESSORS
291
=item C<dispatch> \%ACCESSORS
253 292

  
254 293
May be used to map header fields to custom accessors. Example:
255 294

  
......
273 312

  
274 313
 [
275 314
   offending raw input,
276
   Text::CSV error code if present,
277
   Text::CSV error diagnostics if present,
315
   Text::CSV error code if T:C error, 0 else,
316
   error diagnostics,
278 317
   position in line,
279 318
   estimated line in file,
280 319
 ]
......
294 333

  
295 334
Encoding errors are not dealt with properly.
296 335

  
297
=item *
298

  
299
Errors are not gathered.
300

  
301 336
=back
302 337

  
338
=head1 TODO
339

  
340
Dispatch to child objects, like this:
341

  
342
 $csv = SL::Helper::Csv->new(
343
   file  => ...
344
   class => SL::DB::Part,
345
   dispatch => [
346
     makemodel => {
347
       make_1  => make,
348
       model_1 => model,
349
     },
350
     makemodel => {
351
       make_2  => make,
352
       model_2 => model,
353
     },
354
   ]
355
 );
356

  
303 357
=head1 AUTHOR
304 358

  
305 359
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
t/helper/csv.t
30 30
$csv = SL::Helper::Csv->new(
31 31
  file   => \"Kaffee;0.12;12,2;1,5234\n",
32 32
  header => [ 'description', 'sellprice', 'lastcost_as_number', 'listprice' ],
33
  header_acc => { listprice => 'listprice_as_number' },
33
  dispatch => { listprice => 'listprice_as_number' },
34 34
  class  => 'SL::DB::Part',
35 35
);
36 36
$csv->parse;
37 37

  
38 38
is $csv->get_objects->[0]->sellprice, 0.12, 'numeric attr works';
39 39
is $csv->get_objects->[0]->lastcost, 12.2, 'attr helper works';
40
is $csv->get_objects->[0]->listprice, 1.5234, 'header_acc works';
40
is $csv->get_objects->[0]->listprice, 1.5234, 'dispatch works';
41 41

  
42 42
#####
43 43

  
......
49 49
EOL
50 50
  sep_char => ',',
51 51
  quote_char => "'",
52
  header_acc => { listprice => 'listprice_as_number' },
52
  dispatch => { listprice => 'listprice_as_number' },
53 53
  class  => 'SL::DB::Part',
54 54
);
55 55
$csv->parse;

Auch abrufbar als: Unified diff