fat_table 0.4.0 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -888,8 +888,7 @@ will raise an exception.
888
888
 
889
889
  +last+:: the last non-nil item in the column,
890
890
 
891
- +rng+:: form a string of the form "#{first}..#{last}" to show the range of
892
- values in the column,
891
+ +range+- :: form a Range ~~{min}..{max}~ to show the range of values in the column,
893
892
 
894
893
  +sum+:: for Numeric and String columns, apply '+' to all the non-nil values,
895
894
 
data/TODO.org CHANGED
@@ -1,3 +1,20 @@
1
+ * TODO Conversion to Spreadsheets
2
+ - State "TODO" from [2017-04-21 Fri 10:36]
3
+ This is a [[https://github.com/westonganger/spreadsheet_architect][gem]] that I can include into the Table model to convert a table into
4
+ a spread-sheet, or even a sheet in a multi-sheet spreadsheet file.
5
+
6
+ * TODO Add from_yql for fetching from Yahoo
7
+ - State "TODO" from [2017-04-21 Fri 10:35]
8
+ Add a constructor to allow fetching stock data from yql. Perhaps grab all
9
+ available fields, then allow a select of those of interest.
10
+
11
+ * DONE Allow sorting by expression
12
+ CLOSED: [2022-01-20 Thu 12:47]
13
+ Either by a single string argument as the sole argument to order_by, or use
14
+ another method, such a order_with. Note that this can be done now by creating
15
+ a new column having the sort expression with select and then just order_by
16
+ that column. Perhaps that is an easy way to implement it.
17
+
1
18
  * DONE Ensure that columns resulting from aggregates have proper type
2
19
  CLOSED: [2017-12-29 Fri 05:34]
3
20
  - State "WAIT" from "TODO" [2017-12-29 Fri 05:34]
@@ -5,11 +22,6 @@ CLOSED: [2017-12-29 Fri 05:34]
5
22
  After applying avg, does the column have the proper Numeric or Date, or DateTime
6
23
  type. How about Boolean aggregates?
7
24
 
8
- * TODO Conversion to Spreadsheets
9
- - State "TODO" from [2017-04-21 Fri 10:36]
10
- This is a [[https://github.com/westonganger/spreadsheet_architect][gem]] that I can include into the Table model to convert a table into
11
- a spread-sheet, or even a sheet in a multi-sheet spreadsheet file.
12
-
13
25
  * DONE Formatters
14
26
  CLOSED: [2017-04-21 Fri 10:36]
15
27
  - State "WAIT" from "TODO" [2017-04-21 Fri 10:36]
@@ -31,8 +43,3 @@ CLOSED: [2017-03-02 Thu 15:54]
31
43
  - State "TODO" from [2017-03-02 Thu 15:54]
32
44
  For tables, add a method that eliminates any duplicate rows. Perhaps just apply
33
45
  Array#uniq to the columns?
34
-
35
- * TODO Add from_yql for fetching from Yahoo
36
- - State "TODO" from [2017-04-21 Fri 10:35]
37
- Add a constructor to allow fetching stock data from yql. Perhaps grab all
38
- available fields, then allow a select of those of interest.
@@ -0,0 +1,14 @@
1
+ drop table trans;
2
+ create table trans(date text, code text, raw, shares, price, info text, ok text);
3
+ insert into trans values('2013-05-29', 'S', 15700.00, 6601.85, 24.7790, 'ENTITY3', 'F');
4
+ insert into trans values('2013-05-02', 'P', 118186.40, 118186.4, 11.8500, 'ENTITY1', 'T');
5
+ insert into trans values('2013-05-20', 'S', 12000.00, 5046.00, 28.2804, 'ENTITY3', 'F');
6
+ insert into trans values('2013-05-23', 'S', 8000.00, 3364.00, 27.1083, 'ENTITY3', 'T');
7
+ insert into trans values('2013-05-23', 'S', 39906.00, 16780.47, 25.1749, 'ENTITY3', 'T');
8
+ insert into trans values('2013-05-20', 'S', 85000.00, 35742.50, 28.3224, 'ENTITY3', 'T');
9
+ insert into trans values('2013-05-02', 'P', 795546.20, 795546.2, 1.1850, 'ENTITY1', 'T');
10
+ insert into trans values('2013-05-29', 'S', 13459.00, 5659.51, 24.7464, 'ENTITY3', 'T');
11
+ insert into trans values('2013-05-20', 'S', 33302.00, 14003.49, 28.6383, 'ENTITY3', 'T');
12
+ insert into trans values('2013-05-29', 'S', 15900.00, 6685.95, 24.5802, 'ENTITY3', 'T');
13
+ insert into trans values('2013-05-30', 'S', 6679.00, 2808.52, 25.0471, 'ENTITY3', 'T');
14
+ insert into trans values('2013-05-23', 'S', 23054.00, 9694.21, 26.8015, 'ENTITY3', 'F');
Binary file
Binary file
Binary file
@@ -0,0 +1,8 @@
1
+ \documentclass{article}
2
+
3
+ \usepackage{longtable}
4
+ \usepackage[pdftex,table,x11names]{xcolor}
5
+
6
+ \begin{document}
7
+ \include{quicktable.tex}
8
+ \end{document}
Binary file
@@ -0,0 +1,123 @@
1
+ \begin{longtable}{clcrrc}
2
+ \bfseries{Ref}&
3
+ \multicolumn{1}{c}{\bfseries{Date}}&
4
+ \bfseries{Code}&
5
+ \multicolumn{1}{c}{\bfseries{Shares}}&
6
+ \multicolumn{1}{c}{\bfseries{Price}}&
7
+ \bfseries{Ok}\\
8
+ \endhead
9
+ \bfseries{1}&
10
+ 2013-05-02&
11
+ P&
12
+ \cellcolor{lightgray}{\textcolor{blue}{118,186.4}}&
13
+ \$11.8500&
14
+ Y\\
15
+ \bfseries{2}&
16
+ 2013-05-02&
17
+ P&
18
+ \cellcolor{lightgray}{\textcolor{blue}{795,546.2}}&
19
+ 1.1850&
20
+ Y\\
21
+ \bfseries{Avg}&
22
+ &
23
+ \multicolumn{1}{l}{}&
24
+ \bfseries{456,866.3}&
25
+ \bfseries{6.5175}&
26
+ \\
27
+ \bfseries{3}&
28
+ 2013-05-20&
29
+ S&
30
+ \cellcolor{lightgray}{\textcolor{blue}{5,046.0}}&
31
+ 28.2804&
32
+ N\\
33
+ \bfseries{4}&
34
+ 2013-05-20&
35
+ S&
36
+ \cellcolor{lightgray}{\textcolor{blue}{35,742.5}}&
37
+ 28.3224&
38
+ Y\\
39
+ \bfseries{5}&
40
+ 2013-05-20&
41
+ S&
42
+ \cellcolor{lightgray}{\textcolor{blue}{14,003.5}}&
43
+ 28.6383&
44
+ Y\\
45
+ \bfseries{Avg}&
46
+ &
47
+ \multicolumn{1}{l}{}&
48
+ \bfseries{18,264.0}&
49
+ \bfseries{28.4137}&
50
+ \\
51
+ \bfseries{6}&
52
+ 2013-05-23&
53
+ S&
54
+ \cellcolor{lightgray}{\textcolor{blue}{3,364.0}}&
55
+ 27.1083&
56
+ Y\\
57
+ \bfseries{7}&
58
+ 2013-05-23&
59
+ S&
60
+ \cellcolor{lightgray}{\textcolor{blue}{16,780.5}}&
61
+ 25.1749&
62
+ Y\\
63
+ \bfseries{8}&
64
+ 2013-05-23&
65
+ S&
66
+ \cellcolor{lightgray}{\textcolor{blue}{9,694.2}}&
67
+ 26.8015&
68
+ N\\
69
+ \bfseries{Avg}&
70
+ &
71
+ \multicolumn{1}{l}{}&
72
+ \bfseries{9,946.2}&
73
+ \bfseries{26.3616}&
74
+ \\
75
+ \bfseries{9}&
76
+ 2013-05-29&
77
+ S&
78
+ \cellcolor{lightgray}{\textcolor{blue}{6,601.9}}&
79
+ 24.7790&
80
+ N\\
81
+ \bfseries{10}&
82
+ 2013-05-29&
83
+ S&
84
+ \cellcolor{lightgray}{\textcolor{blue}{5,659.5}}&
85
+ 24.7464&
86
+ Y\\
87
+ \bfseries{11}&
88
+ 2013-05-29&
89
+ S&
90
+ \cellcolor{lightgray}{\textcolor{blue}{6,686.0}}&
91
+ 24.5802&
92
+ Y\\
93
+ \bfseries{Avg}&
94
+ &
95
+ \multicolumn{1}{l}{}&
96
+ \bfseries{6,315.8}&
97
+ \bfseries{24.7019}&
98
+ \\
99
+ \bfseries{12}&
100
+ 2013-05-30&
101
+ S&
102
+ \cellcolor{lightgray}{\textcolor{blue}{2,808.5}}&
103
+ 25.0471&
104
+ Y\\
105
+ \bfseries{Avg}&
106
+ &
107
+ \multicolumn{1}{l}{}&
108
+ \bfseries{2,808.5}&
109
+ \bfseries{25.0471}&
110
+ \\
111
+ \bfseries{Average}&
112
+ &
113
+ \multicolumn{1}{l}{}&
114
+ \bfseries{85,009.9}&
115
+ \bfseries{23.0428}&
116
+ \\
117
+ \bfseries{Total}&
118
+ &
119
+ \multicolumn{1}{l}{}&
120
+ \bfseries{1,020,119.1}&
121
+ \bfseries{}&
122
+ \\
123
+ \end{longtable}
Binary file
@@ -0,0 +1,13 @@
1
+ 'Date', 'Code', 'Raw', 'Shares', 'Price', 'Info', 'Ok',
2
+ '2013-05-29', 'S', 15700.00, 6601.85, 24.7790, 'ENTITY3', FALSE,
3
+ '2013-05-02', 'P', 118186.40, 118186.4, 11.8500, 'ENTITY1', TRUE,
4
+ '2013-05-20', 'S', 12000.00, 5046.00, 28.2804, 'ENTITY3', FALSE,
5
+ '2013-05-23', 'S', 8000.00, 3364.00, 27.1083, 'ENTITY3', TRUE,
6
+ '2013-05-23', 'S', 39906.00, 16780.47, 25.1749, 'ENTITY3', TRUE,
7
+ '2013-05-20', 'S', 85000.00, 35742.50, 28.3224, 'ENTITY3', TRUE,
8
+ '2013-05-02', 'P', 795546.20, 795546.2, 1.1850, 'ENTITY1', TRUE,
9
+ '2013-05-29', 'S', 13459.00, 5659.51, 24.7464, 'ENTITY3', TRUE,
10
+ '2013-05-20', 'S', 33302.00, 14003.49, 28.6383, 'ENTITY3', TRUE,
11
+ '2013-05-29', 'S', 15900.00, 6685.95, 24.5802, 'ENTITY3', TRUE,
12
+ '2013-05-30', 'S', 6679.00, 2808.52, 25.0471, 'ENTITY3', TRUE,
13
+ '2013-05-23', 'S', 23054.00, 9694.21, 26.8015, 'ENTITY3', FALSE
data/fat_table.gemspec CHANGED
@@ -70,6 +70,7 @@ Gem::Specification.new do |spec|
70
70
  spec.add_development_dependency 'rake', '~> 13.0'
71
71
  spec.add_development_dependency 'redcarpet'
72
72
  spec.add_development_dependency 'pg'
73
+ spec.add_development_dependency 'sqlite3'
73
74
  spec.add_development_dependency 'rspec', '~> 3.0'
74
75
  spec.add_development_dependency 'rubocop-rspec'
75
76
  spec.add_development_dependency 'rubocop-performance'
data/lib/ext/array.rb ADDED
@@ -0,0 +1,15 @@
1
+ class Array
2
+ # Map booleans true to 1 and false to 0 so they can be compared in a sort
3
+ # with the <=> operator.
4
+ def map_booleans
5
+ map do |v|
6
+ if v == true
7
+ 1
8
+ elsif v == false
9
+ 0
10
+ else
11
+ v
12
+ end
13
+ end
14
+ end
15
+ end
@@ -83,7 +83,7 @@ module FatTable
83
83
  # col.type #=> 'Numeric'
84
84
  # col.header #=> :prices
85
85
  # col.sum #=> 18376.75
86
- def initialize(header:, items: [], type: 'NilClass')
86
+ def initialize(header:, items: [], type: 'NilClass', tolerant: false)
87
87
  @raw_header = header
88
88
  @header =
89
89
  if @raw_header.is_a?(Symbol)
@@ -92,6 +92,7 @@ module FatTable
92
92
  @raw_header.to_s.as_sym
93
93
  end
94
94
  @type = type
95
+ @tolerant = tolerant
95
96
  msg = "unknown column type '#{type}"
96
97
  raise UserError, msg unless TYPES.include?(@type.to_s)
97
98
 
@@ -141,9 +142,17 @@ module FatTable
141
142
 
142
143
  # :category: Attributes
143
144
 
145
+ # Is this column tolerant of type incompatibilities? If so, the Column
146
+ # type will be forced to String if an incompatible type is found.
147
+ def tolerant?
148
+ @tolerant
149
+ end
150
+
151
+ # :category: Attributes
152
+
144
153
  # Force the column to have String type and then convert all items to
145
154
  # strings.
146
- def force_to_string_type
155
+ def force_string!
147
156
  # msg = "Can only force an empty column to String type"
148
157
  # raise UserError, msg unless empty?
149
158
  @type = 'String'
@@ -175,66 +184,92 @@ module FatTable
175
184
 
176
185
  # The names of the known aggregate operations that can be performed on a
177
186
  # Column.
178
- VALID_AGGREGATES = %s(first last rng
179
- sum count min max avg var dev
187
+ VALID_AGGREGATES = %s(first last range
188
+ sum count min max
189
+ avg var pvar dev pdev
180
190
  any? all? none? one?)
181
191
 
182
192
  # :category: Aggregates
183
193
 
184
194
  # Return the first non-nil item in the Column. Works with any Column type.
185
195
  def first
186
- items.compact.first
196
+ if type == 'String'
197
+ items.reject(&:blank?).first
198
+ else
199
+ items.compact.first
200
+ end
187
201
  end
188
202
 
189
203
  # :category: Aggregates
190
204
 
191
205
  # Return the last non-nil item in the Column. Works with any Column type.
192
206
  def last
193
- items.compact.last
207
+ if type == 'String'
208
+ items.reject(&:blank?).last
209
+ else
210
+ items.compact.last
211
+ end
194
212
  end
195
213
 
196
214
  # :category: Aggregates
197
215
 
198
- # Return a string of the #first and #last non-nil values in the Column.
199
- # Works with any Column type.
200
- def rng
201
- "#{first}..#{last}"
216
+ # Return a count of the non-nil items in the Column. Works with any Column
217
+ # type.
218
+ def count
219
+ if type == 'String'
220
+ items.reject(&:blank?).count.to_d
221
+ else
222
+ items.compact.count.to_d
223
+ end
202
224
  end
203
225
 
204
226
  # :category: Aggregates
205
227
 
206
- # Return the sum of the non-nil items in the Column. Works with numeric and
207
- # string Columns. For a string Column, it will return the concatenation of
208
- # the non-nil items.
209
- def sum
210
- only_with('sum', 'Numeric', 'String')
211
- items.compact.sum
228
+ # Return the smallest non-nil, non-blank item in the Column. Works with
229
+ # numeric, string, and datetime Columns.
230
+ def min
231
+ only_with('min', 'NilClass', 'Numeric', 'String', 'DateTime')
232
+ if type == 'String'
233
+ items.reject(&:blank?).min
234
+ else
235
+ items.compact.min
236
+ end
212
237
  end
213
238
 
214
239
  # :category: Aggregates
215
240
 
216
- # Return a count of the non-nil items in the Column. Works with any Column
217
- # type.
218
- def count
219
- items.compact.count.to_d
241
+ # Return the largest non-nil, non-blank item in the Column. Works with
242
+ # numeric, string, and datetime Columns.
243
+ def max
244
+ only_with('max', 'NilClass', 'Numeric', 'String', 'DateTime')
245
+ if type == 'String'
246
+ items.reject(&:blank?).max
247
+ else
248
+ items.compact.max
249
+ end
220
250
  end
221
251
 
222
252
  # :category: Aggregates
223
253
 
224
- # Return the smallest non-nil item in the Column. Works with numeric,
225
- # string, and datetime Columns.
226
- def min
227
- only_with('min', 'NilClass', 'Numeric', 'String', 'DateTime')
228
- items.compact.min
254
+ # Return a Range object for the smallest to largest value in the column.
255
+ # Works with numeric, string, and datetime Columns.
256
+ def range
257
+ only_with('range', 'NilClass', 'Numeric', 'String', 'DateTime')
258
+ Range.new(min, max)
229
259
  end
230
260
 
231
261
  # :category: Aggregates
232
262
 
233
- # Return the largest non-nil item in the Column. Works with numeric,
234
- # string, and datetime Columns.
235
- def max
236
- only_with('max', 'NilClass', 'Numeric', 'String', 'DateTime')
237
- items.compact.max
263
+ # Return the sum of the non-nil items in the Column. Works with numeric and
264
+ # string Columns. For a string Column, it will return the concatenation of
265
+ # the non-nil items.
266
+ def sum
267
+ only_with('sum', 'Numeric', 'String')
268
+ if type == 'String'
269
+ items.reject(&:blank?).join(' ')
270
+ else
271
+ items.compact.sum
272
+ end
238
273
  end
239
274
 
240
275
  # :category: Aggregates
@@ -374,9 +409,18 @@ module FatTable
374
409
 
375
410
  # Append +itm+ to end of the Column after converting it to the Column's
376
411
  # type. If the Column's type is still open, i.e. NilClass, attempt to fix
377
- # the Column's type based on the type of +itm+ as with Column.new.
412
+ # the Column's type based on the type of +itm+ as with Column.new. If its
413
+ # a tolerant column, respond to type errors by converting the column to a
414
+ # String type.
378
415
  def <<(itm)
379
416
  items << convert_to_type(itm)
417
+ rescue IncompatibleTypeError => ex
418
+ if tolerant?
419
+ force_string!
420
+ retry
421
+ else
422
+ raise ex
423
+ end
380
424
  end
381
425
 
382
426
  # :category: Constructors
@@ -392,187 +436,24 @@ module FatTable
392
436
 
393
437
  private
394
438
 
395
- # Convert val to the type of key, a ruby class constant, such as Date,
396
- # Numeric, etc. If type is NilClass, the type is open, and a non-blank val
397
- # will attempt conversion to one of the allowed types, typing it as a String
398
- # if no other type is recognized. If the val is blank, and the type is nil,
399
- # the Column type remains open. If the val is nil or a blank and the type is
400
- # already determined, the val is set to nil, and should be filtered from any
401
- # Column computations. If the val is non-blank and the Column type
402
- # determined, raise an error if the val cannot be converted to the Column
403
- # type. Otherwise, returns the converted val as an object of the correct
404
- # class.
405
439
  def convert_to_type(val)
406
- case type
407
- when 'NilClass'
408
- if val != false && val.blank?
409
- # Leave the type of the Column open. Unfortunately, false counts as
410
- # blank and we don't want it to. It should be classified as a boolean.
411
- new_val = nil
412
- else
413
- # Only non-blank values are allowed to set the type of the Column
414
- bool_val = convert_to_boolean(val)
415
- new_val =
416
- if bool_val.nil?
417
- convert_to_date_time(val) ||
418
- convert_to_numeric(val) ||
419
- convert_to_string(val)
420
- else
421
- bool_val
422
- end
423
- @type =
424
- if [true, false].include?(new_val)
425
- 'Boolean'
426
- elsif new_val.is_a?(Date) || new_val.is_a?(DateTime)
427
- 'DateTime'
428
- elsif new_val.is_a?(Numeric)
429
- 'Numeric'
430
- elsif new_val.is_a?(String)
431
- 'String'
432
- else
433
- msg = "can't add #{val} of type #{new_val.class.name} to a column"
434
- raise UserError, msg
435
- end
436
- end
437
- new_val
438
- when 'Boolean'
439
- if val.is_a?(String) && val.blank? || val.nil?
440
- nil
441
- else
442
- new_val = convert_to_boolean(val)
443
- if new_val.nil?
444
- msg = "attempt to add '#{val}' to a column already typed as #{type}"
445
- raise UserError, msg
446
- end
447
- new_val
448
- end
449
- when 'DateTime'
450
- if val.blank?
451
- nil
452
- else
453
- new_val = convert_to_date_time(val)
454
- if new_val.nil?
455
- msg = "attempt to add '#{val}' to a column already typed as #{type}"
456
- raise UserError, msg
457
- end
458
- new_val
459
- end
460
- when 'Numeric'
461
- if val.blank?
462
- nil
463
- else
464
- new_val = convert_to_numeric(val)
465
- if new_val.nil?
466
- msg = "attempt to add '#{val}' to a column already typed as #{type}"
467
- raise UserError, msg
468
- end
469
- new_val
470
- end
471
- when 'String'
472
- if val.nil?
473
- nil
474
- else
475
- new_val = convert_to_string(val)
476
- if new_val.nil?
477
- msg = "attempt to add '#{val}' to a column already typed as #{type}"
440
+ new_val = Convert.convert_to_type(val, type)
441
+ if new_val && type == 'NilClass'
442
+ @type =
443
+ if [true, false].include?(new_val)
444
+ 'Boolean'
445
+ elsif new_val.is_a?(Date) || new_val.is_a?(DateTime)
446
+ 'DateTime'
447
+ elsif new_val.is_a?(Numeric)
448
+ 'Numeric'
449
+ elsif new_val.is_a?(String)
450
+ 'String'
451
+ else
452
+ msg = "can't add value '#{val}' of type #{new_val.class.name} to a column"
478
453
  raise UserError, msg
479
454
  end
480
- new_val
481
- end
482
- else
483
- raise UserError, "Mysteriously, column has unknown type '#{type}'"
484
- end
485
- end
486
-
487
- # Convert the val to a boolean if it looks like one, otherwise return nil.
488
- # Any boolean or a string of t, f, true, false, y, n, yes, or no, regardless
489
- # of case is assumed to be a boolean.
490
- def convert_to_boolean(val)
491
- return val if val.is_a?(TrueClass) || val.is_a?(FalseClass)
492
- val = val.to_s.clean
493
- return nil if val.blank?
494
- if val.match?(/\A(false|f|n|no)\z/i)
495
- false
496
- elsif val.match?(/\A(true|t|y|yes)\z/i)
497
- true
498
- end
499
- end
500
-
501
- ISO_DATE_RE = %r{(?<yr>\d\d\d\d)[-\/]
502
- (?<mo>\d\d?)[-\/]
503
- (?<dy>\d\d?)\s*
504
- (T?\s*\d\d:\d\d(:\d\d)?
505
- ([-+](\d\d?)(:\d\d?))?)?}x
506
-
507
- AMR_DATE_RE = %r{(?<dy>\d\d?)[-/](?<mo>\d\d?)[-/](?<yr>\d\d\d\d)\s*
508
- (?<tm>T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?}x
509
-
510
- # A Date like 'Tue, 01 Nov 2016' or 'Tue 01 Nov 2016' or '01 Nov 2016'.
511
- # These are emitted by Postgresql, so it makes from_sql constructor
512
- # possible without special formatting of the dates.
513
- INV_DATE_RE = %r{((mon|tue|wed|thu|fri|sat|sun)[a-zA-z]*,?)?\s+ # looks like dow
514
- (?<dy>\d\d?)\s+ # one or two-digit day
515
- (?<mo_name>[jfmasondJFMASOND][A-Za-z]{2,})\s+ # looks like a month name
516
- (?<yr>\d\d\d\d) # and a 4-digit year
517
- }xi
518
-
519
- # Convert the val to a DateTime if it is either a DateTime, a Date, a Time, or a
520
- # String that can be parsed as a DateTime, otherwise return nil. It only
521
- # recognizes strings that contain a something like '2016-01-14' or '2/12/1985'
522
- # within them, otherwise DateTime.parse would treat many bare numbers as dates,
523
- # such as '2841381', which it would recognize as a valid date, but the user
524
- # probably does not intend it to be so treated.
525
- def convert_to_date_time(val)
526
- return val if val.is_a?(DateTime)
527
- return val if val.is_a?(Date)
528
- return val.to_datetime if val.is_a?(Time)
529
- begin
530
- str = val.to_s.clean
531
- return nil if str.blank?
532
-
533
- if str.match(ISO_DATE_RE)
534
- date = DateTime.parse(val)
535
- elsif str =~ AMR_DATE_RE
536
- date = DateTime.new(Regexp.last_match[:yr].to_i,
537
- Regexp.last_match[:mo].to_i,
538
- Regexp.last_match[:dy].to_i)
539
- elsif str =~ INV_DATE_RE
540
- mo = Date.mo_name_to_num(last_match[:mo_name])
541
- date = DateTime.new(Regexp.last_match[:yr].to_i, mo,
542
- Regexp.last_match[:dy].to_i)
543
- else
544
- return nil
545
- end
546
- # val = val.to_date if
547
- date.seconds_since_midnight.zero? ? date.to_date : date
548
- rescue ArgumentError
549
- nil
550
455
  end
551
- end
552
-
553
- # Convert the val to a Numeric if is already a Numeric or is a String that
554
- # looks like one. Any Float is promoted to a BigDecimal. Otherwise return
555
- # nil.
556
- def convert_to_numeric(val)
557
- return BigDecimal(val, Float::DIG) if val.is_a?(Float)
558
- return val if val.is_a?(Numeric)
559
- # Eliminate any commas, $'s (or other currency symbol), or _'s.
560
- cursym = Regexp.quote(FatTable.currency_symbol)
561
- clean_re = /[,_#{cursym}]/
562
- val = val.to_s.clean.gsub(clean_re, '')
563
- return nil if val.blank?
564
- case val
565
- when /(\A[-+]?\d+\.\d*\z)|(\A[-+]?\d*\.\d+\z)/
566
- BigDecimal(val.to_s.clean)
567
- when /\A[-+]?[\d]+\z/
568
- val.to_i
569
- when %r{\A(?<nm>[-+]?\d+)\s*[:/]\s*(?<dn>[-+]?\d+)\z}
570
- Rational(Regexp.last_match[:nm], Regexp.last_match[:dn])
571
- end
572
- end
573
-
574
- def convert_to_string(val)
575
- val.to_s
456
+ new_val
576
457
  end
577
458
  end
578
459
  end