fat_table 0.2.6 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.rubocop.yml +3 -0
- data/.travis.yml +7 -2
- data/.yardopts +5 -1
- data/README.org +271 -251
- data/README.rdoc +4 -4
- data/TODO.org +7 -0
- data/bin/ft_console +82 -79
- data/fat_table.gemspec +47 -46
- data/lib/fat_table.rb +11 -2
- data/lib/fat_table/column.rb +41 -29
- data/lib/fat_table/db_handle.rb +31 -50
- data/lib/fat_table/evaluator.rb +26 -24
- data/lib/fat_table/formatters/aoa_formatter.rb +5 -6
- data/lib/fat_table/formatters/aoh_formatter.rb +6 -7
- data/lib/fat_table/formatters/formatter.rb +67 -48
- data/lib/fat_table/formatters/latex_formatter.rb +9 -7
- data/lib/fat_table/formatters/org_formatter.rb +8 -9
- data/lib/fat_table/formatters/term_formatter.rb +19 -18
- data/lib/fat_table/formatters/text_formatter.rb +6 -7
- data/lib/fat_table/patches.rb +30 -1
- data/lib/fat_table/table.rb +143 -117
- data/lib/fat_table/version.rb +1 -1
- data/md/README.md +2167 -0
- metadata +78 -84
data/README.rdoc
CHANGED
@@ -485,7 +485,7 @@ Another way to initialize a +FatTable+ table is with the results of a SQL query.
|
|
485
485
|
database parameters to be used for the queries.
|
486
486
|
|
487
487
|
require 'fat_table'
|
488
|
-
FatTable.
|
488
|
+
FatTable.connect(driver: 'Pg',
|
489
489
|
database: 'XXX_development',
|
490
490
|
user: 'dtd',
|
491
491
|
password: 'slflpowert',
|
@@ -493,15 +493,15 @@ database parameters to be used for the queries.
|
|
493
493
|
socket: '/tmp/.s.PGSQL.5432')
|
494
494
|
tab = FatTable.from_sql('select * from trades;')
|
495
495
|
|
496
|
-
Some of the parameters to the +.
|
496
|
+
Some of the parameters to the +.connect+ function have defaults. The driver
|
497
497
|
defaults to 'Pg' for postgresql and the socket defaults to +/tmp/.s.PGSQL.5432+
|
498
498
|
if the host is 'localhost', which it is by default. If the host is not
|
499
499
|
'localhost', the dsn uses a port rather than a socket and defaults to port
|
500
500
|
'5432'. While user and password default to nil, the database parameter is
|
501
501
|
required.
|
502
502
|
|
503
|
-
The +.
|
504
|
-
creates will be used for all subsequent +.from_sql+ calls until +.
|
503
|
+
The +.connect+ function need only be called once, and the database handle it
|
504
|
+
creates will be used for all subsequent +.from_sql+ calls until +.connect+ is
|
505
505
|
called again.
|
506
506
|
|
507
507
|
=== Marking Groups in Input
|
data/TODO.org
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
* DONE Ensure that columns resulting from aggregates have proper type
|
2
|
+
CLOSED: [2017-12-29 Fri 05:34]
|
3
|
+
- State "WAIT" from "TODO" [2017-12-29 Fri 05:34]
|
4
|
+
- State "TODO" from [2017-11-27 Mon 04:46]
|
5
|
+
After applying avg, does the column have the proper Numeric or Date, or DateTime
|
6
|
+
type. How about Boolean aggregates?
|
7
|
+
|
1
8
|
* TODO Conversion to Spreadsheets
|
2
9
|
- State "TODO" from [2017-04-21 Fri 10:36]
|
3
10
|
This is a [[https://github.com/westonganger/spreadsheet_architect][gem]] that I can include into the Table model to convert a table into
|
data/bin/ft_console
CHANGED
@@ -4,22 +4,23 @@ require 'bundler/setup'
|
|
4
4
|
require 'fat_table'
|
5
5
|
require 'pry'
|
6
6
|
|
7
|
-
@data =
|
8
|
-
[
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
@data = [
|
8
|
+
%w[Date Code Raw Shares Price Info Ok],
|
9
|
+
['2013-05-29', 'S', 15_700.00, 6601.85, 24.7790, 'ENTITY3', 'F'],
|
10
|
+
['2013-05-02', 'P', 118_186.40, 118_186.4, 11.8500, 'ENTITY1', 'T'],
|
11
|
+
['2013-05-20', 'S', 12_000.00, 5046.00, 28.2804, 'ENTITY3', 'F'],
|
12
|
+
['2013-05-23', 'S', 8000.00, 3364.00, 27.1083, 'ENTITY3', 'T'],
|
13
|
+
['2013-05-23', 'S', 39_906.00, 16_780.47, 25.1749, 'ENTITY3', 'T'],
|
14
|
+
['2013-05-20', 'S', 85_000.00, 35_742.50, 28.3224, 'ENTITY3', 'T'],
|
15
|
+
['2013-05-02', 'P', 795_546.20, 795_546.2, 1.1850, 'ENTITY1', 'T'],
|
16
|
+
['2013-05-29', 'S', 13_459.00, 5659.51, 24.7464, 'ENTITY3', 'T'],
|
17
|
+
['2013-05-20', 'S', 33_302.00, 14_003.49, 28.6383, 'ENTITY3', 'T'],
|
18
|
+
['2013-05-29', 'S', 15_900.00, 6685.95, 24.5802, 'ENTITY3', 'T'],
|
19
|
+
['2013-05-30', 'S', 6_679.00, 2808.52, 25.0471, 'ENTITY3', 'T'],
|
20
|
+
['2013-05-23', 'S', 23_054.00, 9694.21, 26.8015, 'ENTITY3', 'F']
|
21
|
+
]
|
21
22
|
|
22
|
-
@tab_a_str =
|
23
|
+
@tab_a_str = <<~TABLE
|
23
24
|
| Id | Name | Age | Address | Salary | Join Date |
|
24
25
|
|----+-------+-----+------------+--------+------------|
|
25
26
|
| 1 | Paul | 32 | California | 20000 | 2001-07-13 |
|
@@ -30,85 +31,87 @@ require 'pry'
|
|
30
31
|
| 8 | Paul | 24 | Houston | 20000 | 2005-07-13 |
|
31
32
|
| 9 | James | 44 | Norway | 5000 | 2005-07-13 |
|
32
33
|
| 10 | James | 45 | Texas | 5000 | |
|
33
|
-
|
34
|
+
TABLE
|
34
35
|
|
35
|
-
@tab_b_str =
|
36
|
+
@tab_b_str = <<~TABLE
|
36
37
|
| Id | Dept | Emp Id |
|
37
38
|
|----+-------------+--------|
|
38
39
|
| 1 | IT Billing | 1 |
|
39
40
|
| 2 | Engineering | 2 |
|
40
41
|
| 3 | Finance | 7 |
|
41
|
-
|
42
|
+
TABLE
|
42
43
|
|
43
44
|
@tab_a = FatTable.from_org_string(@tab_a_str)
|
44
45
|
@tab_b = FatTable.from_org_string(@tab_b_str)
|
45
46
|
|
46
|
-
@tab1_str =
|
47
|
-
| Ref | Date | Code | Price | G10 | QP10 | Shares | LP | QP | IPLP | IPQP |
|
48
|
-
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
49
|
-
| T001 | [2016-11-01 Tue] | P | 7.7000 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
50
|
-
| T002 | [2016-11-01 Tue] | P | 7.7500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
51
|
-
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
52
|
-
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
53
|
-
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
54
|
-
| T004 | [2016-11-01 Tue] | S | 7.5500 | T | F | 6811 | 966 | 5845 | 0.2453 | 0.1924 |
|
55
|
-
| T005 | [2016-11-01 Tue] | S | 7.5000 | F | F | 4000 | 572 | 3428 | 0.2453 | 0.1924 |
|
56
|
-
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
57
|
-
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
58
|
-
| T007 | [2016-11-01 Tue] | S | 7.6500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
59
|
-
| T008 | [2016-11-01 Tue] | P | 7.6500 | F | F | 2771 | 393 | 2378 | 0.2453 | 0.1924 |
|
60
|
-
| T009 | [2016-11-01 Tue] | P | 7.6000 | F | F | 9550 | 1363 | 8187 | 0.2453 | 0.1924 |
|
61
|
-
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
62
|
-
| T010 | [2016-11-01 Tue] | P | 7.5500 | F | T | 3175 | 451 | 2724 | 0.2453 | 0.1924 |
|
63
|
-
| T011 | [2016-11-02 Wed] | P | 7.4250 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
64
|
-
| T012 | [2016-11-02 Wed] | P | 7.5500 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
|
65
|
-
| T012 | [2016-11-02 Wed] | P | 7.5500 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
|
66
|
-
| T013 | [2016-11-02 Wed] | P | 7.3500 | T | T | 53100 | 7656 | 45444 | 0.2453 | 0.1924 |
|
67
|
-
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
68
|
-
| T014 | [2016-11-02 Wed] | P | 7.4500 | F | T | 5847 | 835 | 5012 | 0.2453 | 0.1924 |
|
69
|
-
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
70
|
-
| T016 | [2016-11-02 Wed] | P | 8.2500 | T | T | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
71
|
-
|
47
|
+
@tab1_str = <<~TABLE
|
48
|
+
| Ref | Date | Code | Price | G10 | QP10 | Shares | LP | QP | IPLP | IPQP |
|
49
|
+
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
50
|
+
| T001 | [2016-11-01 Tue] | P | 7.7000 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
51
|
+
| T002 | [2016-11-01 Tue] | P | 7.7500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
52
|
+
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
53
|
+
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
54
|
+
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
55
|
+
| T004 | [2016-11-01 Tue] | S | 7.5500 | T | F | 6811 | 966 | 5845 | 0.2453 | 0.1924 |
|
56
|
+
| T005 | [2016-11-01 Tue] | S | 7.5000 | F | F | 4000 | 572 | 3428 | 0.2453 | 0.1924 |
|
57
|
+
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
58
|
+
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
59
|
+
| T007 | [2016-11-01 Tue] | S | 7.6500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
60
|
+
| T008 | [2016-11-01 Tue] | P | 7.6500 | F | F | 2771 | 393 | 2378 | 0.2453 | 0.1924 |
|
61
|
+
| T009 | [2016-11-01 Tue] | P | 7.6000 | F | F | 9550 | 1363 | 8187 | 0.2453 | 0.1924 |
|
62
|
+
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
63
|
+
| T010 | [2016-11-01 Tue] | P | 7.5500 | F | T | 3175 | 451 | 2724 | 0.2453 | 0.1924 |
|
64
|
+
| T011 | [2016-11-02 Wed] | P | 7.4250 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
65
|
+
| T012 | [2016-11-02 Wed] | P | 7.5500 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
|
66
|
+
| T012 | [2016-11-02 Wed] | P | 7.5500 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
|
67
|
+
| T013 | [2016-11-02 Wed] | P | 7.3500 | T | T | 53100 | 7656 | 45444 | 0.2453 | 0.1924 |
|
68
|
+
|------+------------------+------+--------+-----+------+--------+------+-------+--------+--------|
|
69
|
+
| T014 | [2016-11-02 Wed] | P | 7.4500 | F | T | 5847 | 835 | 5012 | 0.2453 | 0.1924 |
|
70
|
+
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
71
|
+
| T016 | [2016-11-02 Wed] | P | 8.2500 | T | T | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
72
|
+
TABLE
|
72
73
|
|
73
|
-
@tab2_str =
|
74
|
-
| Ref | Date | Code | Price | G10 | QP10 | Shares | LP | QP | IPLP | IPQP |
|
75
|
-
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
76
|
-
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
77
|
-
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
78
|
-
| T017 | [2016-11-01 Tue] | P | 8.3 | F | T | 1801 | 1201 | 600 | 0.2453 | 0.1924 |
|
79
|
-
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
80
|
-
| T018 | [2016-11-01 Tue] | S | 7.152 | T | F | 2516 | 2400 | 116 | 0.2453 | 0.1924 |
|
81
|
-
| T018 | [2016-11-01 Tue] | S | 7.152 | T | F | 2516 | 2400 | 116 | 0.2453 | 0.1924 |
|
82
|
-
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
83
|
-
| T007 | [2016-11-01 Tue] | S | 7.6500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
84
|
-
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
85
|
-
| T014 | [2016-11-02 Wed] | P | 7.4500 | F | T | 5847 | 835 | 5012 | 0.2453 | 0.1924 |
|
86
|
-
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
87
|
-
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
88
|
-
| T016 | [2016-11-02 Wed] | P | 8.2500 | T | T | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
89
|
-
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
90
|
-
| T019 | [2017-01-15 Sun] | S | 8.75 | T | F | 300 | 175 | 125 | 0.2453 | 0.1924 |
|
91
|
-
| T020 | [2017-01-19 Thu] | S | 8.25 | F | T | 700 | 615 | 85 | 0.2453 | 0.1924 |
|
92
|
-
| T021 | [2017-01-23 Mon] | P | 7.16 | T | T | 12100 | 11050 | 1050 | 0.2453 | 0.1924 |
|
93
|
-
| T021 | [2017-01-23 Mon] | P | 7.16 | T | T | 12100 | 11050 | 1050 | 0.2453 | 0.1924 |
|
94
|
-
|
74
|
+
@tab2_str = <<~TABLE
|
75
|
+
| Ref | Date | Code | Price | G10 | QP10 | Shares | LP | QP | IPLP | IPQP |
|
76
|
+
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
77
|
+
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
78
|
+
| T003 | [2016-11-01 Tue] | P | 7.5000 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
|
79
|
+
| T017 | [2016-11-01 Tue] | P | 8.3 | F | T | 1801 | 1201 | 600 | 0.2453 | 0.1924 |
|
80
|
+
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
81
|
+
| T018 | [2016-11-01 Tue] | S | 7.152 | T | F | 2516 | 2400 | 116 | 0.2453 | 0.1924 |
|
82
|
+
| T018 | [2016-11-01 Tue] | S | 7.152 | T | F | 2516 | 2400 | 116 | 0.2453 | 0.1924 |
|
83
|
+
| T006 | [2016-11-01 Tue] | S | 7.6000 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
|
84
|
+
| T007 | [2016-11-01 Tue] | S | 7.6500 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
|
85
|
+
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
86
|
+
| T014 | [2016-11-02 Wed] | P | 7.4500 | F | T | 5847 | 835 | 5012 | 0.2453 | 0.1924 |
|
87
|
+
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
88
|
+
| T015 | [2016-11-02 Wed] | P | 7.7500 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
|
89
|
+
| T016 | [2016-11-02 Wed] | P | 8.2500 | T | T | 100 | 14 | 86 | 0.2453 | 0.1924 |
|
90
|
+
|------+------------------+------+--------+-----+------+--------+-------+------+--------+--------|
|
91
|
+
| T019 | [2017-01-15 Sun] | S | 8.75 | T | F | 300 | 175 | 125 | 0.2453 | 0.1924 |
|
92
|
+
| T020 | [2017-01-19 Thu] | S | 8.25 | F | T | 700 | 615 | 85 | 0.2453 | 0.1924 |
|
93
|
+
| T021 | [2017-01-23 Mon] | P | 7.16 | T | T | 12100 | 11050 | 1050 | 0.2453 | 0.1924 |
|
94
|
+
| T021 | [2017-01-23 Mon] | P | 7.16 | T | T | 12100 | 11050 | 1050 | 0.2453 | 0.1924 |
|
95
|
+
TABLE
|
95
96
|
|
96
97
|
@tab1 = FatTable.from_org_string(@tab1_str)
|
97
98
|
@tab2 = FatTable.from_org_string(@tab2_str)
|
98
99
|
|
99
|
-
@aoa = [
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
100
|
+
@aoa = [
|
101
|
+
%w[Ref Date Code Raw Shares Price Info Bool],
|
102
|
+
[1, '2013-05-02', 'P', 795_546.20, 795_546.2, 1.1850, 'YLPEF1', 'T'],
|
103
|
+
[2, '2013-05-02', 'P', 118_186.40, 118_186.4, 11.8500, 'YLPEF1', 'T'],
|
104
|
+
[7, '2013-05-20', 'S', 12_000.00, 5046.00, 28.2804, 'YLEAC', 'F'],
|
105
|
+
[8, '2013-05-20', 'S', 85_000.00, 35_742.50, 28.3224, 'YLEAC', 'T'],
|
106
|
+
[9, '2013-05-20', 'S', 33_302.00, 14_003.49, 28.6383, 'YLEAC', 'T'],
|
107
|
+
[10, '2013-05-23', 'S', 8000.00, 3364.00, 27.1083, 'YLEAC', 'T'],
|
108
|
+
[11, '2013-05-23', 'S', 23_054.00, 9694.21, 26.8015, 'YLEAC', 'F'],
|
109
|
+
[12, '2013-05-23', 'S', 39_906.00, 16_780.47, 25.1749, 'YLEAC', 'T'],
|
110
|
+
[13, '2013-05-29', 'S', 13_459.00, 5659.51, 24.7464, 'YLEAC', 'T'],
|
111
|
+
[14, '2013-05-29', 'S', 15_700.00, 6601.85, 24.7790, 'YLEAC', 'F'],
|
112
|
+
[15, '2013-05-29', 'S', 15_900.00, 6685.95, 24.5802, 'YLEAC', 'T'],
|
113
|
+
[16, '2013-05-30', 'S', 6_679.00, 2808.52, 25.0471, 'YLEAC', 'T']
|
114
|
+
]
|
112
115
|
@tt = FatTable.from_aoa(@aoa)
|
113
116
|
|
114
117
|
Pry.start
|
data/fat_table.gemspec
CHANGED
@@ -1,48 +1,49 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
1
|
lib = File.expand_path('../lib', __FILE__)
|
4
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
3
|
require 'fat_table/version'
|
6
4
|
|
7
5
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
6
|
+
spec.name = 'fat_table'
|
9
7
|
spec.version = FatTable::VERSION
|
10
|
-
spec.authors = [
|
11
|
-
spec.email = [
|
8
|
+
spec.authors = ['Daniel E. Doherty']
|
9
|
+
spec.email = ['ded-law@ddoherty.net']
|
10
|
+
|
11
|
+
spec.summary = 'Provides tools for working with tables as a data type.'
|
12
|
+
spec.description = <<-DESC
|
13
|
+
FatTable is a gem that treats tables as a data type. It provides methods for
|
14
|
+
constructing tables from a variety of sources, building them row-by-row,
|
15
|
+
extracting rows, columns, and cells, and performing aggregate operations on
|
16
|
+
columns. It also provides as set of SQL-esque methods for manipulating table
|
17
|
+
objects: select for filtering by columns or for creating new columns, where
|
18
|
+
for filtering by rows, order_by for sorting rows, distinct for eliminating
|
19
|
+
duplicate rows, group_by for aggregating multiple rows into single rows and
|
20
|
+
applying column aggregate methods to ungrouped columns, a collection of join
|
21
|
+
methods for combining tables, and more.
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
duplicate rows, group_by for aggregating multiple rows into single rows and
|
22
|
-
applying column aggregate methods to ungrouped columns, a collection of join
|
23
|
-
methods for combining tables, and more.
|
23
|
+
Furthermore, FatTable provides methods for formatting tables and producing
|
24
|
+
output that targets various output media: text, ANSI terminals, ruby data
|
25
|
+
structures, LaTeX tables, Emacs org-mode tables, and more. The formatting
|
26
|
+
methods can specify cell formatting in a way that is uniform across all the
|
27
|
+
output methods and can also decorate the output with any number of footers,
|
28
|
+
including group footers. FatTable applies formatting directives to the extent
|
29
|
+
they makes sense for the output medium and treats other formatting directives as
|
30
|
+
no-ops.
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
FatTable can be used to perform operations on data that are naturally best
|
33
|
+
conceived of as tables, which in my experience is quite often. It can also serve
|
34
|
+
as a foundation for providing reporting functions where flexibility about the
|
35
|
+
output medium can be quite useful. Finally FatTable can be used within Emacs
|
36
|
+
org-mode files in code blocks targeting the Ruby language. Org mode tables are
|
37
|
+
presented to a ruby code block as an array of arrays, so FatTable can read
|
38
|
+
them in with its .from_aoa constructor. A FatTable table can output as an
|
39
|
+
array of arrays with its .to_aoa output function and will be rendered in an
|
40
|
+
org-mode buffer as an org-table, ready for processing by other code blocks.
|
41
|
+
DESC
|
33
42
|
|
34
|
-
|
35
|
-
conceived of as tables, which in my experience is quite often. It can also serve
|
36
|
-
as a foundation for providing reporting functions where flexibility about the
|
37
|
-
output medium can be quite useful. Finally FatTable can be used within Emacs
|
38
|
-
org-mode files in code blocks targeting the Ruby language. Org mode tables are
|
39
|
-
presented to a ruby code block as an array of arrays, so FatTable can read
|
40
|
-
them in with its .from_aoa constructor. A FatTable table can output as an
|
41
|
-
array of arrays with its .to_aoa output function and will be rendered in an
|
42
|
-
org-mode buffer as an org-table, ready for processing by other code blocks.
|
43
|
-
}
|
43
|
+
spec.homepage = 'https://github.com/ddoherty03/fat_table'
|
44
44
|
|
45
|
-
|
45
|
+
# Use of squiggle heredocs knocks out older versions.
|
46
|
+
spec.required_ruby_version = '>= 2.2.2'
|
46
47
|
|
47
48
|
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the
|
48
49
|
# 'allowed_push_host' to allow pushing to a single host or delete this section
|
@@ -54,7 +55,7 @@ org-mode buffer as an org-table, ready for processing by other code blocks.
|
|
54
55
|
'public gem pushes.'
|
55
56
|
end
|
56
57
|
|
57
|
-
spec.files
|
58
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
58
59
|
f.match(%r{^(test|spec|features)/})
|
59
60
|
end
|
60
61
|
spec.bindir = 'bin'
|
@@ -62,21 +63,21 @@ org-mode buffer as an org-table, ready for processing by other code blocks.
|
|
62
63
|
spec.require_paths = ['lib']
|
63
64
|
spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
|
64
65
|
|
65
|
-
spec.add_development_dependency '
|
66
|
-
spec.add_development_dependency 'bundler', '~> 1.14'
|
67
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
68
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
66
|
+
spec.add_development_dependency 'bundler'
|
69
67
|
spec.add_development_dependency 'byebug'
|
70
68
|
spec.add_development_dependency 'pry'
|
71
|
-
spec.add_development_dependency 'pry-doc'
|
72
69
|
spec.add_development_dependency 'pry-byebug'
|
70
|
+
spec.add_development_dependency 'pry-doc'
|
71
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
73
72
|
spec.add_development_dependency 'redcarpet'
|
73
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
74
|
+
spec.add_development_dependency 'rubocop-rspec'
|
75
|
+
spec.add_development_dependency 'rubocop-performance'
|
76
|
+
spec.add_development_dependency 'simplecov'
|
74
77
|
|
75
|
-
spec.add_runtime_dependency '
|
76
|
-
spec.add_runtime_dependency '
|
78
|
+
spec.add_runtime_dependency 'activesupport', '>3.0'
|
79
|
+
spec.add_runtime_dependency 'fat_core', '>= 4.1'
|
77
80
|
spec.add_runtime_dependency 'rainbow'
|
78
81
|
spec.add_runtime_dependency 'sequel'
|
79
|
-
spec.add_runtime_dependency '
|
80
|
-
spec.add_runtime_dependency 'sqlite3'
|
81
|
-
spec.add_runtime_dependency 'mysql2'
|
82
|
+
spec.add_runtime_dependency 'gem-path'
|
82
83
|
end
|
data/lib/fat_table.rb
CHANGED
@@ -24,8 +24,17 @@ module FatTable
|
|
24
24
|
require 'fat_table/db_handle'
|
25
25
|
require 'fat_table/errors'
|
26
26
|
|
27
|
+
# Add paths for common db gems to the load paths
|
28
|
+
%w[pg mysql2 sqlite].each do |gem_name|
|
29
|
+
path = Dir.glob("#{ENV['GEM_HOME']}/gems/#{gem_name}*").sort.last
|
30
|
+
if path
|
31
|
+
path = File.join(path, 'lib')
|
32
|
+
$: << path unless $:.include?(path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
27
36
|
# Valid output formats as symbols.
|
28
|
-
FORMATS = [
|
37
|
+
FORMATS = %i[psv aoa aoh latex org term text].freeze
|
29
38
|
|
30
39
|
class << self
|
31
40
|
# Set a default output format to use when FatTable.to_format is invoked.
|
@@ -114,7 +123,7 @@ module FatTable
|
|
114
123
|
end
|
115
124
|
|
116
125
|
# Construct a Table by running a SQL query against the database set up with
|
117
|
-
# FatTable.
|
126
|
+
# FatTable.connect. Return the Table with the query results as rows and the
|
118
127
|
# headers from the query, converted to symbols, as headers.
|
119
128
|
def self.from_sql(query)
|
120
129
|
Table.from_sql(query)
|
data/lib/fat_table/column.rb
CHANGED
@@ -21,14 +21,14 @@ module FatTable
|
|
21
21
|
attr_reader :type
|
22
22
|
|
23
23
|
# An Array of the items of this Column, all of which must be values of the
|
24
|
-
#
|
24
|
+
# Column's type or a nil. This Array contains the value of the item after
|
25
25
|
# conversion to a native Ruby type, such as TrueClass, Date, DateTime,
|
26
26
|
# Integer, String, etc. Thus, you can perform operations on the items,
|
27
27
|
# perhaps after removing nils with +.items.compact+.
|
28
28
|
attr_reader :items
|
29
29
|
|
30
30
|
# Valid Column types as strings.
|
31
|
-
TYPES = %w
|
31
|
+
TYPES = %w[NilClass Boolean DateTime Numeric String].freeze
|
32
32
|
|
33
33
|
# :category: Constructors
|
34
34
|
|
@@ -36,8 +36,8 @@ module FatTable
|
|
36
36
|
# +items+, as an array of either strings or ruby objects that are one of the
|
37
37
|
# permissible types or strings parsable as one of the permissible types. If
|
38
38
|
# no +items+ are passed, returns an empty Column to which items may be added
|
39
|
-
# with the Column#<< method. The item types must be one of the following
|
40
|
-
# strings parseable as one of them:
|
39
|
+
# with the Column#<< method. The item types must be one of the following
|
40
|
+
# types or strings parseable as one of them:
|
41
41
|
#
|
42
42
|
# Boolean::
|
43
43
|
# an object of type TrueClass or FalseClass or a string that is either
|
@@ -48,9 +48,8 @@ module FatTable
|
|
48
48
|
# an object of class Date, DateTime, or a string that matches
|
49
49
|
# +/\d\d\d\d[-\/]\d\d?[-\/]\d\d?/+ and is parseable by DateTime.parse.
|
50
50
|
#
|
51
|
-
# Numeric::
|
52
|
-
#
|
53
|
-
# like a number after removing '+$+', '+,+', and '+_+' as well as Rationals
|
51
|
+
# Numeric:: on object that is of class Numeric, or a string that looks like
|
52
|
+
# a number after removing '+$+', '+,+', and '+_+' as well as Rationals
|
54
53
|
# in the form /<number>:<number>/ or <number>/<number>, where <number>
|
55
54
|
# is an integer.
|
56
55
|
#
|
@@ -91,7 +90,9 @@ module FatTable
|
|
91
90
|
@raw_header.to_s.as_sym
|
92
91
|
end
|
93
92
|
@type = 'NilClass'
|
94
|
-
|
93
|
+
msg = "unknown column type '#{type}"
|
94
|
+
raise UserError, msg unless TYPES.include?(@type.to_s)
|
95
|
+
|
95
96
|
@items = []
|
96
97
|
items.each { |i| self << i }
|
97
98
|
end
|
@@ -103,8 +104,8 @@ module FatTable
|
|
103
104
|
# :category: Attributes
|
104
105
|
|
105
106
|
# Return the item of the Column at the given index.
|
106
|
-
def [](
|
107
|
-
items[
|
107
|
+
def [](idx)
|
108
|
+
items[idx]
|
108
109
|
end
|
109
110
|
|
110
111
|
# :category: Attributes
|
@@ -229,11 +230,13 @@ module FatTable
|
|
229
230
|
# average back to a DateTime.
|
230
231
|
def avg
|
231
232
|
only_with('avg', 'DateTime', 'Numeric')
|
233
|
+
itms = items.compact
|
234
|
+
size = itms.size.to_d
|
232
235
|
if type == 'DateTime'
|
233
|
-
avg_jd =
|
236
|
+
avg_jd = itms.map(&:jd).sum / size
|
234
237
|
DateTime.jd(avg_jd)
|
235
238
|
else
|
236
|
-
sum /
|
239
|
+
itms.sum / size
|
237
240
|
end
|
238
241
|
end
|
239
242
|
|
@@ -342,7 +345,8 @@ module FatTable
|
|
342
345
|
|
343
346
|
def only_with(agg, *valid_types)
|
344
347
|
return self if valid_types.include?(type)
|
345
|
-
|
348
|
+
msg = "aggregate '#{agg}' cannot be applied to a #{type} column"
|
349
|
+
raise UserError, msg
|
346
350
|
end
|
347
351
|
|
348
352
|
public
|
@@ -366,7 +370,8 @@ module FatTable
|
|
366
370
|
# checking for type compatibility. Use the header of this Column as the
|
367
371
|
# header of the new Column.
|
368
372
|
def +(other)
|
369
|
-
|
373
|
+
msg = 'cannot combine columns with different types'
|
374
|
+
raise UserError, msg unless type == other.type
|
370
375
|
Column.new(header: header, items: items + other.items)
|
371
376
|
end
|
372
377
|
|
@@ -401,7 +406,7 @@ module FatTable
|
|
401
406
|
bool_val
|
402
407
|
end
|
403
408
|
@type =
|
404
|
-
if
|
409
|
+
if [true, false].include?(new_val)
|
405
410
|
'Boolean'
|
406
411
|
elsif new_val.is_a?(Date) || new_val.is_a?(DateTime)
|
407
412
|
'DateTime'
|
@@ -410,17 +415,19 @@ module FatTable
|
|
410
415
|
elsif new_val.is_a?(String)
|
411
416
|
'String'
|
412
417
|
else
|
413
|
-
|
418
|
+
msg = "can't add #{val} of type #{new_val.class.name} to a column"
|
419
|
+
raise UserError, msg
|
414
420
|
end
|
415
421
|
end
|
416
422
|
new_val
|
417
423
|
when 'Boolean'
|
418
|
-
if
|
424
|
+
if val.is_a?(String) && val.blank? || val.nil?
|
419
425
|
nil
|
420
426
|
else
|
421
427
|
new_val = convert_to_boolean(val)
|
422
428
|
if new_val.nil?
|
423
|
-
|
429
|
+
msg = "attempt to add '#{val}' to a column already typed as #{type}"
|
430
|
+
raise UserError, msg
|
424
431
|
end
|
425
432
|
new_val
|
426
433
|
end
|
@@ -430,7 +437,8 @@ module FatTable
|
|
430
437
|
else
|
431
438
|
new_val = convert_to_date_time(val)
|
432
439
|
if new_val.nil?
|
433
|
-
|
440
|
+
msg = "attempt to add '#{val}' to a column already typed as #{type}"
|
441
|
+
raise UserError, msg
|
434
442
|
end
|
435
443
|
new_val
|
436
444
|
end
|
@@ -440,7 +448,8 @@ module FatTable
|
|
440
448
|
else
|
441
449
|
new_val = convert_to_numeric(val)
|
442
450
|
if new_val.nil?
|
443
|
-
|
451
|
+
msg = "attempt to add '#{val}' to a column already typed as #{type}"
|
452
|
+
raise UserError, msg
|
444
453
|
end
|
445
454
|
new_val
|
446
455
|
end
|
@@ -450,7 +459,8 @@ module FatTable
|
|
450
459
|
else
|
451
460
|
new_val = convert_to_string(val)
|
452
461
|
if new_val.nil?
|
453
|
-
|
462
|
+
msg = "attempt to add '#{val}' to a column already typed as #{type}"
|
463
|
+
raise UserError, msg
|
454
464
|
end
|
455
465
|
new_val
|
456
466
|
end
|
@@ -466,15 +476,17 @@ module FatTable
|
|
466
476
|
return val if val.is_a?(TrueClass) || val.is_a?(FalseClass)
|
467
477
|
val = val.to_s.clean
|
468
478
|
return nil if val.blank?
|
469
|
-
if val
|
479
|
+
if val.match?(/\A(false|f|n|no)\z/i)
|
470
480
|
false
|
471
|
-
elsif val
|
481
|
+
elsif val.match?(/\A(true|t|y|yes)\z/i)
|
472
482
|
true
|
473
483
|
end
|
474
484
|
end
|
475
485
|
|
476
|
-
IS0_DATE_RE = %r{\b(\d\d\d\d)[-/](\d\d?)[-/](\d\d?)\s*
|
477
|
-
|
486
|
+
IS0_DATE_RE = %r{\b(\d\d\d\d)[-/](\d\d?)[-/](\d\d?)\s*
|
487
|
+
(T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?\b}x
|
488
|
+
AMR_DATE_RE = %r{\b(\d\d?)[-/](\d\d?)[-/](\d\d\d\d)\s*
|
489
|
+
(T\d\d:\d\d:\d\d(\+\d\d:\d\d)?)?\b}x
|
478
490
|
|
479
491
|
# Convert the val to a DateTime if it is either a DateTime, a Date, or a
|
480
492
|
# String that can be parsed as a DateTime, otherwise return nil. It only
|
@@ -488,7 +500,7 @@ module FatTable
|
|
488
500
|
begin
|
489
501
|
val = val.to_s.clean
|
490
502
|
return nil if val.blank?
|
491
|
-
if val
|
503
|
+
if val.match?(IS0_DATE_RE)
|
492
504
|
val = DateTime.parse(val)
|
493
505
|
elsif val =~ AMR_DATE_RE
|
494
506
|
val = DateTime.new($3.to_i, $1.to_i, $2.to_i)
|
@@ -502,11 +514,11 @@ module FatTable
|
|
502
514
|
end
|
503
515
|
end
|
504
516
|
|
505
|
-
# Convert the val to a Numeric if is already a
|
517
|
+
# Convert the val to a Numeric if is already a Numeric or is a String that
|
506
518
|
# looks like one. Any Float is promoted to a BigDecimal. Otherwise return
|
507
519
|
# nil.
|
508
520
|
def convert_to_numeric(val)
|
509
|
-
return BigDecimal
|
521
|
+
return BigDecimal(val, Float::DIG) if val.is_a?(Float)
|
510
522
|
return val if val.is_a?(Numeric)
|
511
523
|
# Eliminate any commas, $'s (or other currency symbol), or _'s.
|
512
524
|
cursym = Regexp.quote(FatTable.currency_symbol)
|
@@ -515,7 +527,7 @@ module FatTable
|
|
515
527
|
return nil if val.blank?
|
516
528
|
case val
|
517
529
|
when /(\A[-+]?\d+\.\d*\z)|(\A[-+]?\d*\.\d+\z)/
|
518
|
-
BigDecimal
|
530
|
+
BigDecimal(val.to_s.clean)
|
519
531
|
when /\A[-+]?[\d]+\z/
|
520
532
|
val.to_i
|
521
533
|
when %r{\A([-+]?\d+)\s*[:/]\s*([-+]?\d+)\z}
|