fat_table 0.2.9 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af65227dda201238ba06b2296e548bcfbab9cc209ad66fc7e5efafe6bbcde8d5
4
- data.tar.gz: f59e53d1ec7aa54a36e96d475f32d50e0d7b668a838476fe3e73f9cd091396f4
3
+ metadata.gz: d95bf4d370e8c501b679aba77975ee9404940383a0058718d4c906b491ef195d
4
+ data.tar.gz: fc39721ae44a5e656bfb8d6225164aa74cf0bdf21246b1eec4c247572b73bf30
5
5
  SHA512:
6
- metadata.gz: 3e5d1f93e4c0fb505afd5f8f5e1c2cb918d31653a4c64ce2db63cd20733fdccd75649f756cb90597c761a61a26d4a76ddaf8a34f7f9f4db8029cd93db62dc70d
7
- data.tar.gz: a6f8b68c21b13382cb6cff7b65f05ed8de120d6e1296ccf2376152da92ba30efbee5196d9b792642e8f3097ed57f11147cc5eac65a330acb4efe4719bae51a79
6
+ metadata.gz: a532d371acf8e0a8fe36e83410c646a12125af501638749bf69f6c85fedcabf7eabf6b6edd5579eb0b32df42220cdac2f7ce018447b2734749e735815ac53ff2
7
+ data.tar.gz: 555e412df95d31e035debb960c5dc86bfba4ec5b4c9827ea7ec19ef2458a18b01f54d4c620e69c621800ddb31bde7ab9e4d7034c9c53380ee301322260647c49
data/.gitignore CHANGED
@@ -13,6 +13,7 @@
13
13
  .rspec_status
14
14
  /README.pdf
15
15
  /README.tex
16
+ /README.md
16
17
  /README.synctex.gz
17
18
  /_minted*
18
19
  /auto/
@@ -24,3 +25,4 @@
24
25
  /GRTAGS
25
26
  /GTAGS
26
27
  /TAGS
28
+ /README.pyg
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ inherit_gem:
2
+ rubocop-shopify: rubocop.yml
3
+ require: rubocop-rspec
4
+ require: rubocop-performance
5
+
6
+ AllCops:
7
+ TargetRubyVersion: 2.7
8
+ Exclude:
9
+ - 'test/tmp/**/*'
10
+ - 'vendor/bundle/**/*'
11
+
12
+ Style/MethodCallWithArgsParentheses:
13
+ Exclude:
14
+ - '**/Gemfile'
15
+
16
+ Style/ClassAndModuleChildren:
17
+ Exclude:
18
+ - 'test/**/*'
data/.travis.yml CHANGED
@@ -2,8 +2,9 @@ language: ruby
2
2
  before_install:
3
3
  - sudo apt-get -qq update
4
4
  - sudo apt-get install -y texlive-latex-base texlive-latex-recommended
5
- before_script:
6
- - createdb -U travis travis
5
+ - gem install pg
6
+ # before_script:
7
+ # - createdb -U travis travis
7
8
  after_failure:
8
9
  - "pwd"
9
10
  - "cat ./spec/tmp/latex.err"
@@ -13,9 +14,9 @@ bundler_args: --without debug
13
14
  services:
14
15
  - postgresql
15
16
  rvm:
16
- - 2.2.2
17
- - 2.3
18
17
  - 2.4
19
18
  - 2.5
20
19
  - 2.6
21
- - ruby-head
20
+ - 2.7
21
+ - 3.0
22
+ - truffleruby
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'rubocop-shopify', require: false
4
+
3
5
  # Specify your gem's dependencies in fat_table.gemspec
4
6
  gemspec
data/README.org CHANGED
@@ -44,17 +44,6 @@ buffer as an org-table, ready for processing by other code blocks.
44
44
 
45
45
  * Installation
46
46
 
47
- ** Prerequisites
48
- The ~fat_table~ gem depends on several libraries being available for building,
49
- mostly those concerned with accessing databases. On an ubuntu system, the
50
- following packages should be installed before you install the ~fat_table~ gem:
51
-
52
- - ruby-dev
53
- - build-essential
54
- - libsqlite3-dev
55
- - libpq-dev
56
- - libmysqlclient-dev
57
-
58
47
  ** Installing the gem
59
48
 
60
49
  Add this line to your application's Gemfile:
@@ -492,7 +481,7 @@ This example illustrates several things:
492
481
  A second ruby data structure that can be used to initialize a ~FatTable~ table
493
482
  is an array of ruby Hashes. Each hash represents a row of the table, and the
494
483
  headers of the table are taken from the keys of the hashes. Accordingly, all the
495
- hashes should have the same keys.
484
+ hashes must have the same keys.
496
485
 
497
486
  This same method can in fact take an array of any objects that can be converted
498
487
  to a Hash with the ~#to_h~ method, so you can use an array of your own objects
@@ -526,9 +515,17 @@ or strings that can be parsed into one of the permissible column types.
526
515
 
527
516
  *** From SQL queries
528
517
 
529
- Another way to initialize a ~FatTable~ table is with the results of a SQL query.
530
- ~FatTable~ uses the ~sequel~ gem to query databases. You must first set the
531
- database parameters to be used for the queries.
518
+ Another way to initialize a ~FatTable~ table is with the results of a SQL
519
+ query. Before you can connect to a database, you need to make sure that the required
520
+ adapter for your database is installed. ~FatTable~ uses the ~sequel~ gem
521
+ under the hood, so any database that it supports can be used. For example, if
522
+ you are accessing a Postgres database, you must install the ~pg~ gem with
523
+
524
+ #+begin_src sh
525
+ $ gem install pg
526
+ #+end_src
527
+
528
+ You must first set the database parameters to be used for the queries.
532
529
 
533
530
  #+BEGIN_SRC ruby
534
531
  # This automatically requires sequel.
@@ -771,17 +768,18 @@ symbol representing an existing column, which has the effect of renaming an
771
768
  existing column, or (2) a string representing a ruby expression for the value of
772
769
  a new column.
773
770
 
774
- Within the string expression, the names of existing or already-specified columns
775
- are available as local variables, as well as the instance variables '@row' and
776
- '@group'. So for our example table, the string expressions for new columns have
777
- access to local variables ~ref~, ~date~, ~code~, ~price~, ~g10~, ~qp10~,
771
+ Within the string expression, the names of existing or already-specified
772
+ columns are available as local variables. In addition the instance variables
773
+ '@row' and '@group' are available as the row number and group number of the
774
+ new value. So for our example table, the string expressions for new columns
775
+ have access to local variables ~ref~, ~date~, ~code~, ~price~, ~g10~, ~qp10~,
778
776
  ~shares~, ~lp~, ~qp~, ~iplp~, and ~ipqp~ as well as the instance variables
779
777
  ~@row~ and ~@group~. The local variables are set to the values of the cell in
780
- their respective columns for each row in the input table and the instance
781
- variables are set the number of the current row and group respectively.
778
+ their respective columns for each row in the input table, and the instance
779
+ variables are set the number of the current row and group number respectively.
782
780
 
783
- For example, if we want to rename the ~:date~ column and add a new column to
784
- compute the cost of shares, we could do the following:
781
+ For example, if we want to rename the ~traded_on~ column to ~:date~ and add a
782
+ new column to compute the cost of shares, we could do the following:
785
783
 
786
784
  #+HEADER: :colnames no :session readme :hlines yes :wrap EXAMPLE :exports both
787
785
  #+BEGIN_SRC ruby
@@ -963,28 +961,21 @@ You can sort a table on any number of columns with ~order_by~. The ~order_by~
963
961
  method takes any number of symbol arguments for the columns to sort on. If you
964
962
  specify more than one column, the sort is performed on the first column, then
965
963
  all columns that are equal with respect to the first column are sorted by the
966
- second column, and so on. All columns of the input table are included in the
967
- output.
964
+ second column, and so on. Ordering is done is ascending order for each of the
965
+ columns, but can be reversed by adding a '!' to the end a symbol argument.
966
+ All columns of the input table are included in the output.
968
967
 
969
- Let's sort our table first by ~:code~, then by ~:date~.
968
+ Let's sort our table first by ~:code~, then in reverse order of ~:date~.
970
969
 
971
970
  #+HEADER: :colnames no :session readme :hlines yes :wrap EXAMPLE :exports both
972
971
  #+BEGIN_SRC ruby
973
- tab1.order_by(:code, :date) \
972
+ tab1.order_by(:code, :date!) \
974
973
  .to_aoa
975
974
  #+END_SRC
976
975
 
977
- #+BEGIN_EXAMPLE
976
+ #+begin_EXAMPLE
978
977
  | Ref | Date | Code | Price | G10 | QP10 | Shares | Lp | Qp | Iplp | Ipqp |
979
978
  |------+------------+------+-------+-----+------+--------+------+-------+--------+--------|
980
- | T001 | 2016-11-01 | P | 7.7 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
981
- | T002 | 2016-11-01 | P | 7.75 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
982
- | T003 | 2016-11-01 | P | 7.5 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
983
- | T003 | 2016-11-01 | P | 7.5 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
984
- | T008 | 2016-11-01 | P | 7.65 | F | F | 2771 | 393 | 2378 | 0.2453 | 0.1924 |
985
- | T009 | 2016-11-01 | P | 7.6 | F | F | 9550 | 1363 | 8187 | 0.2453 | 0.1924 |
986
- | T010 | 2016-11-01 | P | 7.55 | F | T | 3175 | 451 | 2724 | 0.2453 | 0.1924 |
987
- |------+------------+------+-------+-----+------+--------+------+-------+--------+--------|
988
979
  | T011 | 2016-11-02 | P | 7.425 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
989
980
  | T012 | 2016-11-02 | P | 7.55 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
990
981
  | T012 | 2016-11-02 | P | 7.55 | F | F | 4700 | 677 | 4023 | 0.2453 | 0.1924 |
@@ -993,12 +984,20 @@ Let's sort our table first by ~:code~, then by ~:date~.
993
984
  | T015 | 2016-11-02 | P | 7.75 | F | F | 500 | 72 | 428 | 0.2453 | 0.1924 |
994
985
  | T016 | 2016-11-02 | P | 8.25 | T | T | 100 | 14 | 86 | 0.2453 | 0.1924 |
995
986
  |------+------------+------+-------+-----+------+--------+------+-------+--------+--------|
987
+ | T001 | 2016-11-01 | P | 7.7 | T | F | 100 | 14 | 86 | 0.2453 | 0.1924 |
988
+ | T002 | 2016-11-01 | P | 7.75 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
989
+ | T003 | 2016-11-01 | P | 7.5 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
990
+ | T003 | 2016-11-01 | P | 7.5 | F | T | 800 | 112 | 688 | 0.2453 | 0.1924 |
991
+ | T008 | 2016-11-01 | P | 7.65 | F | F | 2771 | 393 | 2378 | 0.2453 | 0.1924 |
992
+ | T009 | 2016-11-01 | P | 7.6 | F | F | 9550 | 1363 | 8187 | 0.2453 | 0.1924 |
993
+ | T010 | 2016-11-01 | P | 7.55 | F | T | 3175 | 451 | 2724 | 0.2453 | 0.1924 |
994
+ |------+------------+------+-------+-----+------+--------+------+-------+--------+--------|
996
995
  | T004 | 2016-11-01 | S | 7.55 | T | F | 6811 | 966 | 5845 | 0.2453 | 0.1924 |
997
996
  | T005 | 2016-11-01 | S | 7.5 | F | F | 4000 | 572 | 3428 | 0.2453 | 0.1924 |
998
997
  | T006 | 2016-11-01 | S | 7.6 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
999
998
  | T006 | 2016-11-01 | S | 7.6 | F | T | 1000 | 143 | 857 | 0.2453 | 0.1924 |
1000
999
  | T007 | 2016-11-01 | S | 7.65 | T | F | 200 | 28 | 172 | 0.2453 | 0.1924 |
1001
- #+END_EXAMPLE
1000
+ #+end_EXAMPLE
1002
1001
 
1003
1002
  The interesting thing about ~order_by~ is that, while it ignores groups in its
1004
1003
  input, it adds group boundaries in the output table at those rows where the sort
@@ -1043,8 +1042,10 @@ the value is a symbol for one of several aggregating methods that
1043
1042
  to the :price column so that the output shows the average price in each group.
1044
1043
  The ~:shares~, ~:lp~, and ~:qp~ columns are summed, and the ~:any?~ aggregate is
1045
1044
  applied to one of the boolean fields, that is, it is ~true~ if any of the values
1046
- in that column are ~true~. The column names in the output of the aggregated
1047
- columns have the name of the aggregating method pre-pended to the column name.
1045
+ in that column are ~true~.
1046
+
1047
+ Note that the column names in the output of the aggregated columns have the
1048
+ name of the aggregating method pre-pended to the column name.
1048
1049
 
1049
1050
  Here is a list of all the aggregate methods available. If the description
1050
1051
  restricts the aggregate to particular column types, applying it to other types
@@ -1313,6 +1314,7 @@ table where the join expression is satisfied and augmented with nils otherwise.
1313
1314
  Finally, a cross join outputs every row of ~tab_a~ augmented with every row of
1314
1315
  ~tab_b~, in other words, the Cartesian product of the two tables. If ~tab_a~ has
1315
1316
  ~N~ rows and ~tab_b~ has ~M~ rows, the output table will have ~N * M~ rows.
1317
+ So be careful lest you consume all your computer's memory.
1316
1318
 
1317
1319
  #+HEADER: :colnames no :session readme :hlines yes :wrap EXAMPLE :exports both
1318
1320
  #+BEGIN_SRC ruby
@@ -1350,10 +1352,10 @@ Finally, a cross join outputs every row of ~tab_a~ augmented with every row of
1350
1352
 
1351
1353
  *** Set Operations
1352
1354
 
1353
- ~FatTable~ can perform several set operations on tables. In order for two tables
1354
- to be used this way, they must have the same number of columns with the same
1355
- types or an exception will be raised. We'll call two tables that qualify for
1356
- combining with set operations "set-compatible."
1355
+ ~FatTable~ can perform several set operations on pairs of tables. In order for
1356
+ two tables to be used this way, they must have the same number of columns with
1357
+ the same types or an exception will be raised. We'll call two tables that
1358
+ qualify for combining with set operations "set-compatible."
1357
1359
 
1358
1360
  We'll use the following two set-compatible tables in the examples. They each
1359
1361
  have some duplicates and some group boundaries so you can see the effect of the
@@ -1765,9 +1767,9 @@ but ruby data structures, and for them, things such as alignment are irrelevant.
1765
1767
  array of array,
1766
1768
 
1767
1769
  These are all implemented by classes that inherit from ~FatTable::Formatter~
1768
- class by defining about a dozen methods that get called at various places during
1769
- the construction of the output table. The idea is that more classes can be
1770
- defined by adding additional classes.
1770
+ class by defining about a dozen methods that get called at various places
1771
+ during the construction of the output table. The idea is that more output
1772
+ formats can be defined by adding additional classes.
1771
1773
 
1772
1774
  *** Table Locations
1773
1775
 
data/fat_table.gemspec CHANGED
@@ -1,7 +1,6 @@
1
1
  lib = File.expand_path('../lib', __FILE__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
  require 'fat_table/version'
4
- require 'fat_table/patches'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = 'fat_table'
@@ -10,7 +9,7 @@ Gem::Specification.new do |spec|
10
9
  spec.email = ['ded-law@ddoherty.net']
11
10
 
12
11
  spec.summary = 'Provides tools for working with tables as a data type.'
13
- spec.description = <<-DESC.strip_heredoc
12
+ spec.description = <<-DESC
14
13
  FatTable is a gem that treats tables as a data type. It provides methods for
15
14
  constructing tables from a variety of sources, building them row-by-row,
16
15
  extracting rows, columns, and cells, and performing aggregate operations on
@@ -64,22 +63,22 @@ Gem::Specification.new do |spec|
64
63
  spec.require_paths = ['lib']
65
64
  spec.metadata['yard.run'] = 'yri' # use "yard" to build full HTML docs.
66
65
 
67
- spec.add_development_dependency 'bundler', '~> 1.14'
66
+ spec.add_development_dependency 'bundler'
68
67
  spec.add_development_dependency 'byebug'
69
68
  spec.add_development_dependency 'pry'
70
69
  spec.add_development_dependency 'pry-byebug'
71
70
  spec.add_development_dependency 'pry-doc'
72
- spec.add_development_dependency 'rake', '~> 10.0'
71
+ spec.add_development_dependency 'rake', '~> 13.0'
73
72
  spec.add_development_dependency 'redcarpet'
73
+ spec.add_development_dependency 'pg'
74
74
  spec.add_development_dependency 'rspec', '~> 3.0'
75
75
  spec.add_development_dependency 'rubocop-rspec'
76
+ spec.add_development_dependency 'rubocop-performance'
76
77
  spec.add_development_dependency 'simplecov'
77
78
 
78
79
  spec.add_runtime_dependency 'activesupport', '>3.0'
79
- spec.add_runtime_dependency 'fat_core', '~> 4.0', '>= 4.1'
80
- spec.add_runtime_dependency 'mysql2'
81
- spec.add_runtime_dependency 'pg'
80
+ spec.add_runtime_dependency 'fat_core', '>= 4.9.0'
82
81
  spec.add_runtime_dependency 'rainbow'
83
82
  spec.add_runtime_dependency 'sequel'
84
- spec.add_runtime_dependency 'sqlite3'
83
+ spec.add_runtime_dependency 'gem-path'
85
84
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Column objects are a thin wrapper around an Array to allow columns to be
3
5
  # summed and have other aggregate operations performed on them, but compacting
@@ -137,6 +139,19 @@ module FatTable
137
139
  size - 1
138
140
  end
139
141
 
142
+ # :category: Attributes
143
+
144
+ # Force the column to have String type and then convert all items to
145
+ # strings.
146
+ def force_to_string_type
147
+ # msg = "Can only force an empty column to String type"
148
+ # raise UserError, msg unless empty?
149
+ @type = 'String'
150
+ unless empty?
151
+ @items = items.map(&:to_s)
152
+ end
153
+ end
154
+
140
155
  ##########################################################################
141
156
  # Enumerable
142
157
  ##########################################################################
@@ -483,34 +498,55 @@ module FatTable
483
498
  end
484
499
  end
485
500
 
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
490
-
491
- # Convert the val to a DateTime if it is either a DateTime, a Date, or a
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
492
520
  # String that can be parsed as a DateTime, otherwise return nil. It only
493
- # recognizes strings that contain a something like '2016-01-14' or
494
- # '2/12/1985' within them, otherwise DateTime.parse would treat many bare
495
- # numbers as dates, such as '2841381', which it would recognize as a valid
496
- # date, but the user probably does not intend it to be so treated.
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.
497
525
  def convert_to_date_time(val)
498
526
  return val if val.is_a?(DateTime)
499
527
  return val if val.is_a?(Date)
528
+ return val.to_datetime if val.is_a?(Time)
500
529
  begin
501
- val = val.to_s.clean
502
- return nil if val.blank?
503
- if val.match?(IS0_DATE_RE)
504
- val = DateTime.parse(val)
505
- elsif val =~ AMR_DATE_RE
506
- val = DateTime.new($3.to_i, $1.to_i, $2.to_i)
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)
507
543
  else
508
544
  return nil
509
545
  end
510
- val = val.to_date if val.seconds_since_midnight.zero?
511
- val
546
+ # val = val.to_date if
547
+ date.seconds_since_midnight.zero? ? date.to_date : date
512
548
  rescue ArgumentError
513
- return nil
549
+ nil
514
550
  end
515
551
  end
516
552
 
@@ -530,8 +566,8 @@ module FatTable
530
566
  BigDecimal(val.to_s.clean)
531
567
  when /\A[-+]?[\d]+\z/
532
568
  val.to_i
533
- when %r{\A([-+]?\d+)\s*[:/]\s*([-+]?\d+)\z}
534
- Rational($1, $2)
569
+ when %r{\A(?<nm>[-+]?\d+)\s*[:/]\s*(?<dn>[-+]?\d+)\z}
570
+ Rational(Regexp.last_match[:nm], Regexp.last_match[:dn])
535
571
  end
536
572
  end
537
573
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Set and access a database by module-level methods.
2
4
  module FatTable
3
5
  class << self
@@ -20,8 +22,9 @@ module FatTable
20
22
  #
21
23
  # +adapter+::
22
24
  # One of 'pg' (for Postgresql), 'mysql' or 'mysql2' (for Mysql), or
23
- # 'sqlite' (for SQLite3) to specify the +Sequel+ driver to use. You may
24
- # have to install the driver to make this work. By default use 'Pg'.
25
+ # 'sqlite' (for SQLite3) (or any other adapter supported by the +Sequel+
26
+ # gem) to specify the driver to use. You may have to install the
27
+ # appropriate driver to make this work.
25
28
  #
26
29
  # +database+::
27
30
  # The name of the database to access. There is no default for this.
@@ -55,8 +58,17 @@ module FatTable
55
58
  # Set the dsn for Sequel
56
59
  begin
57
60
  self.handle = Sequel.connect(args)
58
- rescue Sequel::Error => ex
59
- raise TransientError, "#{args}: #{ex}"
61
+ rescue Sequel::AdapterNotFound => ex
62
+ case ex.to_s
63
+ when /pg/
64
+ raise TransientError, 'You need to install the postgres adapter pg'
65
+ when /mysql/
66
+ raise TransientError, 'You need to install the mysql adapter'
67
+ when /sqlite/
68
+ raise TransientError, 'You need to install the sqlite adapter'
69
+ else
70
+ raise ex
71
+ end
60
72
  end
61
73
  handle
62
74
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Raised when the caller of the code made an error that the caller can
3
5
  # correct.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # The Evaluator class provides a class for evaluating Ruby expressions based
3
5
  # on variable settings provided at runtime. If the same Evaluator object is
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A subclass of Formatter for rendering the table as a Ruby Array of Arrays.
3
5
  # Each cell is formatted as a string in accordance with the formatting
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A subclass of Formatter for rendering the table as a Ruby Array of Hashes.
3
5
  # Each row of the Array is a Hash representing one row of the table with the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A Formatter is for use in Table output routines, and provides methods for
3
5
  # adding group and table footers to the output and instructions for how the
@@ -73,7 +75,7 @@ module FatTable
73
75
  false_color: 'none',
74
76
  false_bgcolor: 'none',
75
77
  underline: false,
76
- blink: false
78
+ blink: false,
77
79
  }
78
80
 
79
81
  class_attribute :valid_colors
@@ -247,7 +249,7 @@ module FatTable
247
249
  cols.each do |c|
248
250
  hsh[c] = :avg
249
251
  end
250
- footer('Average', hsh)
252
+ footer('Average', **hsh)
251
253
  end
252
254
 
253
255
  # :category: Footers
@@ -258,7 +260,7 @@ module FatTable
258
260
  cols.each do |c|
259
261
  hsh[c] = :avg
260
262
  end
261
- gfooter('Group Average', hsh)
263
+ gfooter('Group Average', **hsh)
262
264
  end
263
265
 
264
266
  # :category: Footers
@@ -270,7 +272,7 @@ module FatTable
270
272
  cols.each do |c|
271
273
  hsh[c] = :min
272
274
  end
273
- footer('Minimum', hsh)
275
+ footer('Minimum', **hsh)
274
276
  end
275
277
 
276
278
  # :category: Footers
@@ -282,7 +284,7 @@ module FatTable
282
284
  cols.each do |c|
283
285
  hsh[c] = :min
284
286
  end
285
- gfooter('Group Minimum', hsh)
287
+ gfooter('Group Minimum', **hsh)
286
288
  end
287
289
 
288
290
  # :category: Footers
@@ -294,7 +296,7 @@ module FatTable
294
296
  cols.each do |c|
295
297
  hsh[c] = :max
296
298
  end
297
- footer('Maximum', hsh)
299
+ footer('Maximum', **hsh)
298
300
  end
299
301
 
300
302
  # :category: Footers
@@ -306,7 +308,7 @@ module FatTable
306
308
  cols.each do |c|
307
309
  hsh[c] = :max
308
310
  end
309
- gfooter('Group Maximum', hsh)
311
+ gfooter('Group Maximum', **hsh)
310
312
  end
311
313
 
312
314
  # :category: Formatting
@@ -418,7 +420,7 @@ module FatTable
418
420
  # \n\[niltext\]:: render a nil item with the given text.
419
421
  def format(**fmts)
420
422
  %i[header bfirst gfirst body footer gfooter].each do |loc|
421
- format_for(loc, fmts)
423
+ format_for(loc, **fmts)
422
424
  end
423
425
  self
424
426
  end
@@ -577,9 +579,9 @@ module FatTable
577
579
  # parse, we remove the matched construct from fmt. At the end, any
578
580
  # remaining characters in fmt should be invalid.
579
581
  fmt_hash = {}
580
- if fmt =~ /c\[(#{CLR_RE})(\.(#{CLR_RE}))?\]/
581
- fmt_hash[:color] = $1 unless $1.blank?
582
- fmt_hash[:bgcolor] = $3 unless $3.blank?
582
+ if fmt =~ /c\[(?<co>#{CLR_RE})(\.(?<bg>#{CLR_RE}))?\]/
583
+ fmt_hash[:color] = Regexp.last_match[:co] unless Regexp.last_match[:co].blank?
584
+ fmt_hash[:bgcolor] = Regexp.last_match[:bg] unless Regexp.last_match[:bg].blank?
583
585
  validate_color(fmt_hash[:color])
584
586
  validate_color(fmt_hash[:bgcolor])
585
587
  fmt = fmt.sub($&, '')
@@ -599,12 +601,12 @@ module FatTable
599
601
  fmt_hash[:case] = :title
600
602
  fmt = fmt.sub($&, '')
601
603
  end
602
- if fmt =~ /(~\s*)?B/
603
- fmt_hash[:bold] = !$1
604
+ if fmt =~ /(?<neg>~\s*)?B/
605
+ fmt_hash[:bold] = !Regexp.last_match[:neg]
604
606
  fmt = fmt.sub($&, '')
605
607
  end
606
- if fmt =~ /(~\s*)?I/
607
- fmt_hash[:italic] = !$1
608
+ if fmt =~ /(?<neg>~\s*)?I/
609
+ fmt_hash[:italic] = !Regexp.last_match[:neg]
608
610
  fmt = fmt.sub($&, '')
609
611
  end
610
612
  if fmt =~ /R/
@@ -619,12 +621,12 @@ module FatTable
619
621
  fmt_hash[:alignment] = :left
620
622
  fmt = fmt.sub($&, '')
621
623
  end
622
- if fmt =~ /(~\s*)?_/
623
- fmt_hash[:underline] = !$1
624
+ if fmt =~ /(?<neg>~\s*)?_/
625
+ fmt_hash[:underline] = !Regexp.last_match[:neg]
624
626
  fmt = fmt.sub($&, '')
625
627
  end
626
- if fmt =~ /(~\s*)?\*/
627
- fmt_hash[:blink] = !$1
628
+ if fmt =~ /(?<neg>~\s*)?\*/
629
+ fmt_hash[:blink] = !Regexp.last_match[:neg]
628
630
  fmt = fmt.sub($&, '')
629
631
  end
630
632
  [fmt_hash, fmt]
@@ -639,9 +641,9 @@ module FatTable
639
641
  # parse, we remove the matched construct from fmt. At the end, any
640
642
  # remaining characters in fmt should be invalid.
641
643
  fmt_hash = {}
642
- if fmt =~ /n\[\s*([^\]]*)\s*\]/
643
- fmt_hash[:nil_text] = $1.clean
644
- fmt = fmt.sub($&, '')
644
+ if fmt =~ /n\[\s*(?<bdy>[^\]]*)\s*\]/
645
+ fmt_hash[:nil_text] = Regexp.last_match[:bdy].clean
646
+ fmt = fmt.sub(Regexp.last_match[0], '')
645
647
  end
646
648
  [fmt_hash, fmt]
647
649
  end
@@ -655,22 +657,22 @@ module FatTable
655
657
  # parse, we remove the matched construct from fmt. At the end, any
656
658
  # remaining characters in fmt should be invalid.
657
659
  fmt_hash, fmt = parse_str_fmt(fmt)
658
- if fmt =~ /(\d+).(\d+)/
659
- fmt_hash[:pre_digits] = $1.to_i
660
- fmt_hash[:post_digits] = $2.to_i
661
- fmt = fmt.sub($&, '')
660
+ if fmt =~ /(?<pre>\d+).(?<post>\d+)/
661
+ fmt_hash[:pre_digits] = Regexp.last_match[:pre].to_i
662
+ fmt_hash[:post_digits] = Regexp.last_match[:post].to_i
663
+ fmt = fmt.sub(Regexp.last_match[0], '')
662
664
  end
663
- if fmt =~ /(~\s*)?,/
664
- fmt_hash[:commas] = !$1
665
- fmt = fmt.sub($&, '')
665
+ if fmt =~ /(?<neg>~\s*)?,/
666
+ fmt_hash[:commas] = !Regexp.last_match[:neg]
667
+ fmt = fmt.sub(Regexp.last_match[0], '')
666
668
  end
667
- if fmt =~ /(~\s*)?\$/
668
- fmt_hash[:currency] = !$1
669
- fmt = fmt.sub($&, '')
669
+ if fmt =~ /(?<neg>~\s*)?\$/
670
+ fmt_hash[:currency] = !Regexp.last_match[:neg]
671
+ fmt = fmt.sub(Regexp.last_match[0], '')
670
672
  end
671
- if fmt =~ /(~\s*)?H/
672
- fmt_hash[:hms] = !$1
673
- fmt = fmt.sub($&, '')
673
+ if fmt =~ /(?<neg>~\s*)?H/
674
+ fmt_hash[:hms] = !Regexp.last_match[:neg]
675
+ fmt = fmt.sub(Regexp.last_match[0], '')
674
676
  end
675
677
  unless fmt.blank? || !strict
676
678
  raise UserError, "unrecognized numeric formatting instructions '#{fmt}'"
@@ -688,13 +690,13 @@ module FatTable
688
690
  # parse, we remove the matched construct from fmt. At the end, any
689
691
  # remaining characters in fmt should be invalid.
690
692
  fmt_hash, fmt = parse_str_fmt(fmt)
691
- if fmt =~ /d\[([^\]]*)\]/
692
- fmt_hash[:date_fmt] = $1
693
- fmt = fmt.sub($&, '')
693
+ if fmt =~ /d\[(?<bdy>[^\]]*)\]/
694
+ fmt_hash[:date_fmt] = Regexp.last_match[:bdy]
695
+ fmt = fmt.sub(Regexp.last_match[0], '')
694
696
  end
695
- if fmt =~ /D\[([^\]]*)\]/
696
- fmt_hash[:date_fmt] = $1
697
- fmt = fmt.sub($&, '')
697
+ if fmt =~ /D\[(?<bdy>[^\]]*)\]/
698
+ fmt_hash[:date_fmt] = Regexp.last_match[:bdy]
699
+ fmt = fmt.sub(Regexp.last_match[0], '')
698
700
  end
699
701
  unless fmt.blank? || !strict
700
702
  msg = "unrecognized datetime formatting instructions '#{fmt}'"
@@ -712,37 +714,38 @@ module FatTable
712
714
  # parse, we remove the matched construct from fmt. At the end, any
713
715
  # remaining characters in fmt should be invalid.
714
716
  fmt_hash = {}
715
- if fmt =~ /b\[\s*([^\],]*),([^\]]*)\s*\]/
716
- fmt_hash[:true_text] = $1.clean
717
- fmt_hash[:false_text] = $2.clean
718
- fmt = fmt.sub($&, '')
717
+ if fmt =~ /b\[\s*(?<t>[^\],]*),(?<f>[^\]]*)\s*\]/
718
+ fmt_hash[:true_text] = Regexp.last_match[:t].clean
719
+ fmt_hash[:false_text] = Regexp.last_match[:f].clean
720
+ fmt = fmt.sub(Regexp.last_match[0], '')
719
721
  end
720
722
  # Since true_text, false_text and nil_text may want to have internal
721
723
  # spaces, defer removing extraneous spaces until after they are parsed.
722
724
  if fmt =~ /c\[(#{CLR_RE})(\.(#{CLR_RE}))?,
723
725
  \s*(#{CLR_RE})(\.(#{CLR_RE}))?\]/x
724
- fmt_hash[:true_color] = $1 unless $1.blank?
725
- fmt_hash[:true_bgcolor] = $3 unless $3.blank?
726
- fmt_hash[:false_color] = $4 unless $4.blank?
727
- fmt_hash[:false_bgcolor] = $6 unless $6.blank?
728
- fmt = fmt.sub($&, '')
726
+ tco, _, tbg, fco, _, fbg = Regexp.last_match.captures
727
+ fmt_hash[:true_color] = tco unless tco.blank?
728
+ fmt_hash[:true_bgcolor] = tbg unless tbg.blank?
729
+ fmt_hash[:false_color] = fco unless fco.blank?
730
+ fmt_hash[:false_bgcolor] = fbg unless fbg.blank?
731
+ fmt = fmt.sub(Regexp.last_match[0], '')
729
732
  end
730
733
  str_fmt_hash, fmt = parse_str_fmt(fmt)
731
734
  fmt_hash = fmt_hash.merge(str_fmt_hash)
732
735
  if fmt =~ /Y/
733
736
  fmt_hash[:true_text] = 'Y'
734
737
  fmt_hash[:false_text] = 'N'
735
- fmt = fmt.sub($&, '')
738
+ fmt = fmt.sub(Regexp.last_match[0], '')
736
739
  end
737
740
  if fmt =~ /T/
738
741
  fmt_hash[:true_text] = 'T'
739
742
  fmt_hash[:false_text] = 'F'
740
- fmt = fmt.sub($&, '')
743
+ fmt = fmt.sub(Regexp.last_match[0], '')
741
744
  end
742
745
  if fmt =~ /X/
743
746
  fmt_hash[:true_text] = 'X'
744
747
  fmt_hash[:false_text] = ''
745
- fmt = fmt.sub($&, '')
748
+ fmt = fmt.sub(Regexp.last_match[0], '')
746
749
  end
747
750
  unless fmt.blank? || !strict
748
751
  raise UserError, "unrecognized boolean formatting instructions '#{fmt}'"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Output the table in the same way as org-mode for emacs does. This is almost
3
5
  # identical to TextFormatter except that dates do get formatted as inactive
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rainbow'
2
4
 
3
5
  module FatTable
@@ -26,10 +28,10 @@ module FatTable
26
28
  super
27
29
  @options[:unicode] = options.fetch(:unicode, true)
28
30
  @options[:framecolor] = options.fetch(:framecolor, 'none.none')
29
- return unless @options[:framecolor] =~ /([-_a-zA-Z]*)(\.([-_a-zA-Z]*))/
31
+ return unless @options[:framecolor] =~ /(?<co>[-_a-zA-Z]*)(\.(?<bg>[-_a-zA-Z]*))/
30
32
 
31
- @options[:frame_fg] = $1.downcase unless $1.blank?
32
- @options[:frame_bg] = $3.downcase unless $3.blank?
33
+ @options[:frame_fg] = Regexp.last_match[:co].downcase unless Regexp.last_match[:co].blank?
34
+ @options[:frame_bg] = Regexp.last_match[:bg].downcase unless Regexp.last_match[:bg].blank?
33
35
  end
34
36
 
35
37
  # Valid colors for ANSI terminal using the rainbow gem's X11ColorNames.
@@ -101,18 +103,18 @@ module FatTable
101
103
  # Unicode line-drawing characters. We use double lines before and after the
102
104
  # table and single lines for the sides and hlines between groups and
103
105
  # footers.
104
- UPPER_LEFT = "\u2552".freeze
105
- UPPER_RIGHT = "\u2555".freeze
106
- DOUBLE_RULE = "\u2550".freeze
107
- UPPER_TEE = "\u2564".freeze
108
- VERTICAL_RULE = "\u2502".freeze
109
- LEFT_TEE = "\u251C".freeze
110
- HORIZONTAL_RULE = "\u2500".freeze
111
- SINGLE_CROSS = "\u253C".freeze
112
- RIGHT_TEE = "\u2524".freeze
113
- LOWER_LEFT = "\u2558".freeze
114
- LOWER_RIGHT = "\u255B".freeze
115
- LOWER_TEE = "\u2567".freeze
106
+ UPPER_LEFT = "\u2552"
107
+ UPPER_RIGHT = "\u2555"
108
+ DOUBLE_RULE = "\u2550"
109
+ UPPER_TEE = "\u2564"
110
+ VERTICAL_RULE = "\u2502"
111
+ LEFT_TEE = "\u251C"
112
+ HORIZONTAL_RULE = "\u2500"
113
+ SINGLE_CROSS = "\u253C"
114
+ RIGHT_TEE = "\u2524"
115
+ LOWER_LEFT = "\u2558"
116
+ LOWER_RIGHT = "\u255B"
117
+ LOWER_TEE = "\u2567"
116
118
  # :startdoc:
117
119
 
118
120
  def upper_left
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # Output the table as plain text. This is almost identical to OrgFormatter
3
5
  # except that dates do not get formatted as inactive timestamps and the
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'fat_table/formatters/formatter'
2
4
  require 'fat_table/formatters/aoa_formatter'
3
5
  require 'fat_table/formatters/aoh_formatter'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  unless { a: 1 }.respond_to?(:fetch_values)
2
4
  # Add fetch_values if this version of ruby does not define it.
3
5
  class Hash
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # A container for a two-dimensional table. All cells in the table must be a
3
5
  # String, a DateTime (or Date), a Numeric (Bignum, Integer, or BigDecimal), or
@@ -156,7 +158,8 @@ module FatTable
156
158
  raise UserError, msg if FatTable.db.nil?
157
159
 
158
160
  result = Table.new
159
- FatTable.db[query].each do |h|
161
+ rows = FatTable.db[query]
162
+ rows.each do |h|
160
163
  result << h
161
164
  end
162
165
  result
@@ -295,6 +298,8 @@ module FatTable
295
298
  # :category: Attributes
296
299
 
297
300
  # Return the table's Column with the given +key+ as its header.
301
+ # @param key [Symbol] symbol for header of column to return
302
+ # @return [FatTable::Column]
298
303
  def column(key)
299
304
  columns.detect { |c| c.header == key.as_sym }
300
305
  end
@@ -309,6 +314,15 @@ module FatTable
309
314
 
310
315
  # :category: Attributes
311
316
 
317
+ # Set the column type for Column with the given +key+ as a String type,
318
+ # but only if empty. Otherwise, we would have to worry about converting
319
+ # existing items in the column to String. Perhaps that's a TODO.
320
+ def set_column_to_string_type(key)
321
+ column(key).force_to_string_type
322
+ end
323
+
324
+ # :category: Attributes
325
+
312
326
  # Return the array of items of the column with the given header symbol
313
327
  # +key+, or if +key+ is an Integer, return that row at that index. So a
314
328
  # table's rows can be accessed by number, and its columns can be accessed by
@@ -880,10 +894,7 @@ module FatTable
880
894
  # Apply the set operation given by ~oper~ between this table and the other
881
895
  # table given in the first argument. If distinct is true, eliminate
882
896
  # duplicates from the result.
883
- def set_operation(other, oper = :+,
884
- distinct: true,
885
- add_boundaries: true,
886
- inherit_boundaries: false)
897
+ def set_operation(other, oper = :+, distinct: true, add_boundaries: true, inherit_boundaries: false)
887
898
  unless columns.size == other.columns.size
888
899
  msg = "can't apply set ops to tables with a different number of columns"
889
900
  raise UserError, msg
@@ -981,6 +992,11 @@ module FatTable
981
992
  #
982
993
  # Any groups present in either Table are eliminated in the output Table. See
983
994
  # the README for examples.
995
+ # @param other [FatTable::Table] table to join with self
996
+ # @param exps [Array<String>, Array<Symbol>] table to join with self
997
+ # @param join_type [Array<String>, Array<Symbol>] type of join :inner, :left, :right, :full, :cross
998
+ # @return [FatTable::Table] result of joining self to other
999
+ #
984
1000
  def join(other, *exps, join_type: :inner)
985
1001
  unless other.is_a?(Table)
986
1002
  raise UserError, 'need other table as first argument to join'
@@ -1083,10 +1099,10 @@ module FatTable
1083
1099
  # Translate any remaining row_b heads to append '_b' if they have the
1084
1100
  # same name as a row_a key.
1085
1101
  a_heads = row_a.keys
1086
- row_b = row_b.to_a.each.map { |k, v|
1102
+ row_b = row_b.to_a.each.map do |k, v|
1087
1103
  [a_heads.include?(k) ? "#{k}_b".to_sym : k, v]
1088
- }.to_h
1089
- row_a.merge(row_b)
1104
+ end
1105
+ row_a.merge(row_b.to_h)
1090
1106
  end
1091
1107
 
1092
1108
  # Return a hash for the local variables of a join expression in which all
@@ -1125,7 +1141,7 @@ module FatTable
1125
1141
  [nat_exp, common_heads]
1126
1142
  end
1127
1143
  else
1128
- # We have expressions to evaluate
1144
+ # We have join expressions to evaluate
1129
1145
  and_conds = []
1130
1146
  partial_result = nil
1131
1147
  last_sym = nil
@@ -1133,8 +1149,8 @@ module FatTable
1133
1149
  case exp
1134
1150
  when Symbol
1135
1151
  case exp.to_s.clean
1136
- when /\A(.*)_a\z/
1137
- a_head = $1.to_sym
1152
+ when /\A(?<sy>.*)_a\z/
1153
+ a_head = Regexp.last_match[:sy].to_sym
1138
1154
  unless a_heads.include?(a_head)
1139
1155
  raise UserError, "no column '#{a_head}' in table"
1140
1156
  end
@@ -1149,11 +1165,11 @@ module FatTable
1149
1165
  partial_result = nil
1150
1166
  else
1151
1167
  # First of a pair of _a or _b
1152
- partial_result = "(#{a_head}_a == "
1168
+ partial_result = String.new("(#{a_head}_a == ")
1153
1169
  end
1154
1170
  last_sym = a_head
1155
- when /\A(.*)_b\z/
1156
- b_head = $1.to_sym
1171
+ when /\A(?<sy>.*)_b\z/
1172
+ b_head = Regexp.last_match[:sy].to_sym
1157
1173
  unless b_heads.include?(b_head)
1158
1174
  raise UserError, "no column '#{b_head}' in second table"
1159
1175
  end
@@ -1168,7 +1184,7 @@ module FatTable
1168
1184
  partial_result = nil
1169
1185
  else
1170
1186
  # First of a pair of _a or _b
1171
- partial_result = "(#{b_head}_b == "
1187
+ partial_result = String.new("(#{b_head}_b == ")
1172
1188
  end
1173
1189
  b_common_heads << b_head
1174
1190
  last_sym = b_head
@@ -1275,6 +1291,15 @@ module FatTable
1275
1291
 
1276
1292
  # :category: Constructors
1277
1293
 
1294
+ # Add a group boundary mark at the given row, or at the end of the table
1295
+ # by default.
1296
+ def add_boundary(at_row = nil)
1297
+ row = at_row || (size - 1)
1298
+ @boundaries << row
1299
+ end
1300
+
1301
+ # :category: Constructors
1302
+
1278
1303
  # Add a +row+ represented by a Hash having the headers as keys. If +mark:+
1279
1304
  # is set true, mark this row as a boundary. All tables should be built
1280
1305
  # ultimately using this method as a primitive.
@@ -1284,7 +1309,7 @@ module FatTable
1284
1309
  columns << Column.new(header: k) unless column?(k)
1285
1310
  column(key) << v
1286
1311
  end
1287
- @boundaries << (size - 1) if mark
1312
+ add_boundary if mark
1288
1313
  self
1289
1314
  end
1290
1315
 
@@ -1353,9 +1378,9 @@ module FatTable
1353
1378
 
1354
1379
  method = "to_#{fmt}"
1355
1380
  if block_given?
1356
- send method, options, &Proc.new
1381
+ send(method, options, &Proc.new)
1357
1382
  else
1358
- send method, options
1383
+ send(method, options)
1359
1384
  end
1360
1385
  end
1361
1386
 
@@ -1369,7 +1394,7 @@ module FatTable
1369
1394
  # default format for Formatter, there is no class PsvFormatter as you might
1370
1395
  # expect.
1371
1396
  def to_psv(options = {})
1372
- fmt = Formatter.new(self, options)
1397
+ fmt = Formatter.new(self, **options)
1373
1398
  yield fmt if block_given?
1374
1399
  fmt.output
1375
1400
  end
@@ -1382,7 +1407,7 @@ module FatTable
1382
1407
  # the block to which formatting instructions and footers can be added by
1383
1408
  # calling methods on it.
1384
1409
  def to_aoa(options = {})
1385
- fmt = FatTable::AoaFormatter.new(self, options)
1410
+ fmt = FatTable::AoaFormatter.new(self, **options)
1386
1411
  yield fmt if block_given?
1387
1412
  fmt.output
1388
1413
  end
@@ -1396,7 +1421,7 @@ module FatTable
1396
1421
  # given, it yields an AohFormatter to the block to which formatting
1397
1422
  # instructions and footers can be added by calling methods on it.
1398
1423
  def to_aoh(options = {})
1399
- fmt = AohFormatter.new(self, options)
1424
+ fmt = AohFormatter.new(self, **options)
1400
1425
  yield fmt if block_given?
1401
1426
  fmt.output
1402
1427
  end
@@ -1409,7 +1434,7 @@ module FatTable
1409
1434
  # LaTeXFormatter to the block to which formatting instructions and footers
1410
1435
  # can be added by calling methods on it.
1411
1436
  def to_latex(options = {})
1412
- fmt = LaTeXFormatter.new(self, options)
1437
+ fmt = LaTeXFormatter.new(self, **options)
1413
1438
  yield fmt if block_given?
1414
1439
  fmt.output
1415
1440
  end
@@ -1422,7 +1447,7 @@ module FatTable
1422
1447
  # OrgFormatter to the block to which formatting instructions and footers can
1423
1448
  # be added by calling methods on it.
1424
1449
  def to_org(options = {})
1425
- fmt = OrgFormatter.new(self, options)
1450
+ fmt = OrgFormatter.new(self, **options)
1426
1451
  yield fmt if block_given?
1427
1452
  fmt.output
1428
1453
  end
@@ -1435,7 +1460,7 @@ module FatTable
1435
1460
  # given, it yields a TermFormatter to the block to which formatting
1436
1461
  # instructions and footers can be added by calling methods on it.
1437
1462
  def to_term(options = {})
1438
- fmt = TermFormatter.new(self, options)
1463
+ fmt = TermFormatter.new(self, **options)
1439
1464
  yield fmt if block_given?
1440
1465
  fmt.output
1441
1466
  end
@@ -1449,7 +1474,7 @@ module FatTable
1449
1474
  # footers can be added by calling methods on it.
1450
1475
  # @return [String]
1451
1476
  def to_text(options = {})
1452
- fmt = TextFormatter.new(self, options)
1477
+ fmt = TextFormatter.new(self, **options)
1453
1478
  yield fmt if block_given?
1454
1479
  fmt.output
1455
1480
  end
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FatTable
2
4
  # The current version of FatTable
3
- VERSION = '0.2.9'.freeze
5
+ VERSION = '0.3.3'
4
6
  end
data/lib/fat_table.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This module provides objects for treating tables as a data type on which you
2
4
  # can (1) perform operations, such as select, where, join, and others and (2)
3
5
  # output the tables in several formats, including text, ANSI terminal, LaTeX,
@@ -24,6 +26,15 @@ module FatTable
24
26
  require 'fat_table/db_handle'
25
27
  require 'fat_table/errors'
26
28
 
29
+ # Add paths for common db gems to the load paths
30
+ %w[pg mysql2 sqlite].each do |gem_name|
31
+ path = Dir.glob("#{ENV['GEM_HOME']}/gems/#{gem_name}*").sort.last
32
+ if path
33
+ path = File.join(path, 'lib')
34
+ $LOAD_PATH << path unless $LOAD_PATH.include?(path)
35
+ end
36
+ end
37
+
27
38
  # Valid output formats as symbols.
28
39
  FORMATS = %i[psv aoa aoh latex org term text].freeze
29
40
 
@@ -149,9 +160,9 @@ module FatTable
149
160
  raise UserError, "unknown format '#{fmt}'" unless FORMATS.include?(fmt)
150
161
  method = "to_#{fmt}"
151
162
  if block_given?
152
- send method, table, options, &Proc.new
163
+ send(method, table, options, &Proc.new)
153
164
  else
154
- send method, table, options
165
+ send(method, table, options)
155
166
  end
156
167
  end
157
168
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fat_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel E. Doherty
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-04 00:00:00.000000000 Z
11
+ date: 2022-01-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.14'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.14'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: byebug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: '13.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '10.0'
96
+ version: '13.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: redcarpet
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pg
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rspec
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -137,7 +151,7 @@ dependencies:
137
151
  - !ruby/object:Gem::Version
138
152
  version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
- name: simplecov
154
+ name: rubocop-performance
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
157
  - - ">="
@@ -151,67 +165,47 @@ dependencies:
151
165
  - !ruby/object:Gem::Version
152
166
  version: '0'
153
167
  - !ruby/object:Gem::Dependency
154
- name: activesupport
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">"
158
- - !ruby/object:Gem::Version
159
- version: '3.0'
160
- type: :runtime
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">"
165
- - !ruby/object:Gem::Version
166
- version: '3.0'
167
- - !ruby/object:Gem::Dependency
168
- name: fat_core
168
+ name: simplecov
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: '4.0'
174
171
  - - ">="
175
172
  - !ruby/object:Gem::Version
176
- version: '4.1'
177
- type: :runtime
173
+ version: '0'
174
+ type: :development
178
175
  prerelease: false
179
176
  version_requirements: !ruby/object:Gem::Requirement
180
177
  requirements:
181
- - - "~>"
182
- - !ruby/object:Gem::Version
183
- version: '4.0'
184
178
  - - ">="
185
179
  - !ruby/object:Gem::Version
186
- version: '4.1'
180
+ version: '0'
187
181
  - !ruby/object:Gem::Dependency
188
- name: mysql2
182
+ name: activesupport
189
183
  requirement: !ruby/object:Gem::Requirement
190
184
  requirements:
191
- - - ">="
185
+ - - ">"
192
186
  - !ruby/object:Gem::Version
193
- version: '0'
187
+ version: '3.0'
194
188
  type: :runtime
195
189
  prerelease: false
196
190
  version_requirements: !ruby/object:Gem::Requirement
197
191
  requirements:
198
- - - ">="
192
+ - - ">"
199
193
  - !ruby/object:Gem::Version
200
- version: '0'
194
+ version: '3.0'
201
195
  - !ruby/object:Gem::Dependency
202
- name: pg
196
+ name: fat_core
203
197
  requirement: !ruby/object:Gem::Requirement
204
198
  requirements:
205
199
  - - ">="
206
200
  - !ruby/object:Gem::Version
207
- version: '0'
201
+ version: 4.9.0
208
202
  type: :runtime
209
203
  prerelease: false
210
204
  version_requirements: !ruby/object:Gem::Requirement
211
205
  requirements:
212
206
  - - ">="
213
207
  - !ruby/object:Gem::Version
214
- version: '0'
208
+ version: 4.9.0
215
209
  - !ruby/object:Gem::Dependency
216
210
  name: rainbow
217
211
  requirement: !ruby/object:Gem::Requirement
@@ -241,7 +235,7 @@ dependencies:
241
235
  - !ruby/object:Gem::Version
242
236
  version: '0'
243
237
  - !ruby/object:Gem::Dependency
244
- name: sqlite3
238
+ name: gem-path
245
239
  requirement: !ruby/object:Gem::Requirement
246
240
  requirements:
247
241
  - - ">="
@@ -264,7 +258,8 @@ description: |2
264
258
  duplicate rows, group_by for aggregating multiple rows into single rows and
265
259
  applying column aggregate methods to ungrouped columns, a collection of join
266
260
  methods for combining tables, and more.
267
- Furthermore, FatTable provides methods for formatting tables and producing
261
+
262
+ Furthermore, FatTable provides methods for formatting tables and producing
268
263
  output that targets various output media: text, ANSI terminals, ruby data
269
264
  structures, LaTeX tables, Emacs org-mode tables, and more. The formatting
270
265
  methods can specify cell formatting in a way that is uniform across all the
@@ -272,7 +267,8 @@ description: |2
272
267
  including group footers. FatTable applies formatting directives to the extent
273
268
  they makes sense for the output medium and treats other formatting directives as
274
269
  no-ops.
275
- FatTable can be used to perform operations on data that are naturally best
270
+
271
+ FatTable can be used to perform operations on data that are naturally best
276
272
  conceived of as tables, which in my experience is quite often. It can also serve
277
273
  as a foundation for providing reporting functions where flexibility about the
278
274
  output medium can be quite useful. Finally FatTable can be used within Emacs
@@ -290,6 +286,7 @@ extra_rdoc_files: []
290
286
  files:
291
287
  - ".gitignore"
292
288
  - ".rspec"
289
+ - ".rubocop.yml"
293
290
  - ".travis.yml"
294
291
  - ".yardopts"
295
292
  - Gemfile
@@ -323,7 +320,7 @@ licenses: []
323
320
  metadata:
324
321
  allowed_push_host: https://rubygems.org
325
322
  yard.run: yri
326
- post_install_message:
323
+ post_install_message:
327
324
  rdoc_options: []
328
325
  require_paths:
329
326
  - lib
@@ -338,8 +335,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
338
335
  - !ruby/object:Gem::Version
339
336
  version: '0'
340
337
  requirements: []
341
- rubygems_version: 3.0.3
342
- signing_key:
338
+ rubygems_version: 3.3.3
339
+ signing_key:
343
340
  specification_version: 4
344
341
  summary: Provides tools for working with tables as a data type.
345
342
  test_files: []