tablesmith 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -1
- data/.rubocop.yml +112 -2
- data/.ruby-version +1 -1
- data/.travis.yml +21 -0
- data/Appraisals +19 -0
- data/Gemfile +2 -0
- data/README.md +112 -11
- data/Rakefile +4 -2
- data/gemfiles/activerecord_4.gemfile +8 -0
- data/gemfiles/activerecord_5.1.gemfile +8 -0
- data/gemfiles/activerecord_5.2.gemfile +8 -0
- data/gemfiles/activerecord_6.0.gemfile +8 -0
- data/lib/tablesmith.rb +2 -0
- data/lib/tablesmith/active_record_source.rb +4 -2
- data/lib/tablesmith/array_rows_source.rb +3 -1
- data/lib/tablesmith/hash_rows_base.rb +4 -1
- data/lib/tablesmith/hash_rows_source.rb +8 -8
- data/lib/tablesmith/html_formatter.rb +1 -0
- data/lib/tablesmith/table.rb +34 -32
- data/lib/tablesmith/version.rb +3 -1
- data/spec/active_record_table_spec.rb +51 -49
- data/spec/array_table_spec.rb +61 -2
- data/spec/fixtures.rb +2 -0
- data/spec/hash_rows_table_spec.rb +15 -12
- data/spec/hash_table_spec.rb +23 -1
- data/spec/spec_helper.rb +6 -2
- data/spec/table_spec.rb +5 -3
- data/tablesmith.gemspec +15 -10
- metadata +77 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f7a031da03b4834e3512f66e1ee9541826d6dfdd7992d593dbbf686f9b5029d0
|
4
|
+
data.tar.gz: fcca01f815f5b51e31ff1c148e8137edec52a5405e54588216305e50d5ff1a3f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0e1360f9d29e4b9439253b5e6e40279842df875daa2d926f30b265ab32531befe69911dbe3f436cf4c99b0d0adb00188180e9aa5578f7b1f48a121a52149c2f6
|
7
|
+
data.tar.gz: e93c2e664a4c3809c557dc173643d9d38bc51c8913252490bbd46065e1a7c877fe54af44d8140a788e6478c083f93542dcf5fb2abaa8585a98cd44da32840a76
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -4,8 +4,118 @@ require:
|
|
4
4
|
AllCops:
|
5
5
|
TargetRubyVersion: 2.3
|
6
6
|
|
7
|
-
Layout/
|
7
|
+
Layout/ClassStructure:
|
8
8
|
Enabled: true
|
9
|
+
Categories:
|
10
|
+
module_inclusion:
|
11
|
+
- include
|
12
|
+
- prepend
|
13
|
+
- extend
|
14
|
+
association:
|
15
|
+
- has_many
|
16
|
+
- has_one
|
17
|
+
- belongs_to
|
18
|
+
- has_and_belongs_to_many
|
19
|
+
validations:
|
20
|
+
- validate
|
21
|
+
- validates_inclusion_of
|
22
|
+
- validates_presence_of
|
23
|
+
callbacks:
|
24
|
+
- before_initialize
|
25
|
+
- before_validation
|
26
|
+
- before_save
|
27
|
+
- before_create
|
28
|
+
- before_update
|
29
|
+
- before_destroy
|
30
|
+
- after_save
|
31
|
+
- after_create
|
32
|
+
- after_validation
|
33
|
+
- after_initialize
|
34
|
+
- after_update
|
35
|
+
- after_destroy
|
36
|
+
enums:
|
37
|
+
- enum
|
38
|
+
scopes:
|
39
|
+
- scope
|
40
|
+
ExpectedOrder:
|
41
|
+
- association
|
42
|
+
- module_inclusion
|
43
|
+
- validations
|
44
|
+
- constants
|
45
|
+
- enums
|
46
|
+
- callbacks
|
47
|
+
- scopes
|
48
|
+
- public_class_methods
|
49
|
+
- initializer
|
50
|
+
- public_methods
|
51
|
+
- protected_methods
|
52
|
+
- private_methods
|
53
|
+
|
54
|
+
Layout/DotPosition:
|
55
|
+
EnforcedStyle: trailing
|
56
|
+
|
57
|
+
Lint/Void:
|
58
|
+
Exclude:
|
59
|
+
- 'spec/**'
|
60
|
+
|
61
|
+
Metrics:
|
62
|
+
Enabled: true
|
63
|
+
|
64
|
+
Metrics/AbcSize:
|
65
|
+
Max: 20
|
66
|
+
|
67
|
+
Metrics/BlockLength:
|
68
|
+
Exclude:
|
69
|
+
- 'Rakefile'
|
70
|
+
- '**/*.rake'
|
71
|
+
- 'spec/**/*.rb'
|
72
|
+
- 'test/**/*.rb'
|
73
|
+
ExcludedMethods: ['included', 'namespace']
|
74
|
+
|
75
|
+
Metrics/ClassLength:
|
76
|
+
Exclude:
|
77
|
+
- 'Rakefile'
|
78
|
+
- 'spec/**/*.rb'
|
79
|
+
- 'test/**/*.rb'
|
80
|
+
|
81
|
+
Metrics/LineLength:
|
82
|
+
Enabled: false
|
83
|
+
Max: 120
|
84
|
+
AllowHeredoc: true
|
85
|
+
AllowURI: true
|
86
|
+
URISchemes: http, https
|
87
|
+
|
88
|
+
Metrics/MethodLength:
|
89
|
+
CountComments: false # count full line comments?
|
90
|
+
Max: 15
|
91
|
+
|
92
|
+
Rails/Date:
|
93
|
+
Enabled: true
|
94
|
+
EnforcedStyle: flexible
|
95
|
+
|
96
|
+
Rails/RefuteMethods:
|
97
|
+
Enabled: true
|
98
|
+
|
99
|
+
Rails/TimeZone:
|
100
|
+
Enabled: true
|
101
|
+
EnforcedStyle: flexible
|
102
|
+
|
103
|
+
Style/ClassAndModuleChildren:
|
104
|
+
Enabled: false
|
9
105
|
|
10
106
|
Style/Documentation:
|
11
|
-
Enabled: false
|
107
|
+
Enabled: false
|
108
|
+
|
109
|
+
Style/DocumentationMethod:
|
110
|
+
Enabled: false
|
111
|
+
|
112
|
+
Style/FrozenStringLiteralComment:
|
113
|
+
EnforcedStyle: when_needed
|
114
|
+
Enabled: true
|
115
|
+
|
116
|
+
# Technically this performs better, and I got no problem with it.
|
117
|
+
Style/ParallelAssignment:
|
118
|
+
Enabled: false
|
119
|
+
|
120
|
+
Style/WhenThen:
|
121
|
+
Enabled: true
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.5
|
data/.travis.yml
CHANGED
@@ -1 +1,22 @@
|
|
1
1
|
language: ruby
|
2
|
+
|
3
|
+
rvm:
|
4
|
+
- 2.4.6
|
5
|
+
- 2.5.5
|
6
|
+
- 2.6.5
|
7
|
+
- 2.7.0
|
8
|
+
|
9
|
+
gemfile:
|
10
|
+
- gemfiles/activerecord_4.gemfile
|
11
|
+
- gemfiles/activerecord_5.1.gemfile
|
12
|
+
- gemfiles/activerecord_5.2.gemfile
|
13
|
+
- gemfiles/activerecord_6.0.gemfile
|
14
|
+
|
15
|
+
before_install: gem install bundler -v 2.1.2
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
exclude:
|
19
|
+
- rvm: 2.4.6
|
20
|
+
gemfile: gemfiles/activerecord_6.0.gemfile
|
21
|
+
- rvm: 2.7.0
|
22
|
+
gemfile: gemfiles/activerecord_4.gemfile
|
data/Appraisals
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
appraise 'activerecord-4' do
|
2
|
+
gem 'activerecord', '~> 4.0'
|
3
|
+
gem 'sqlite3', '~> 1.3.6'
|
4
|
+
end
|
5
|
+
|
6
|
+
appraise 'activerecord-5.1' do
|
7
|
+
gem 'activerecord', '~> 5.1.0'
|
8
|
+
gem 'sqlite3', '~> 1.4'
|
9
|
+
end
|
10
|
+
|
11
|
+
appraise 'activerecord-5.2' do
|
12
|
+
gem 'activerecord', '~> 5.2.0'
|
13
|
+
gem 'sqlite3', '~> 1.4'
|
14
|
+
end
|
15
|
+
|
16
|
+
appraise 'activerecord-6.0' do
|
17
|
+
gem 'activerecord', '~> 6.0.0'
|
18
|
+
gem 'sqlite3', '~> 1.4'
|
19
|
+
end
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/livingsocial/tablesmith.svg?branch=master)](https://travis-ci.org/livingsocial/tablesmith)
|
2
|
+
|
1
3
|
# Tablesmith
|
2
4
|
|
3
|
-
Drop-in gem for console tables for Hash,
|
5
|
+
Drop-in gem for console tables for Array, Hash, and ActiveRecord.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -18,18 +20,117 @@ Or install it yourself as:
|
|
18
20
|
|
19
21
|
## Usage
|
20
22
|
|
21
|
-
|
23
|
+
### In irb or pry
|
24
|
+
|
25
|
+
```
|
26
|
+
require 'tablesmith'
|
27
|
+
|
28
|
+
> [[:foo, :bar], [1,3]].to_table
|
29
|
+
=> +-----+-----+
|
30
|
+
| foo | bar |
|
31
|
+
+-----+-----+
|
32
|
+
| 1 | 3 |
|
33
|
+
+-----+-----+
|
34
|
+
|
35
|
+
> {a: 1, b: 2}.to_table
|
36
|
+
=> +---+---+
|
37
|
+
| a | b |
|
38
|
+
+---+---+
|
39
|
+
| 1 | 2 |
|
40
|
+
+---+---+
|
41
|
+
|
42
|
+
> [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table
|
43
|
+
=> +----------+-----+
|
44
|
+
| date | amt |
|
45
|
+
+----------+-----+
|
46
|
+
| 1/1/2020 | 35 |
|
47
|
+
| 1/2/2020 | 80 |
|
48
|
+
+----------+-----+
|
49
|
+
|
50
|
+
> p1 = Person.create(first_name: 'chrismo', custom_attributes: { instrument: 'piano', style: 'jazz' })
|
51
|
+
=> #<Person:0x00007fac3eb406a8 id: 1, first_name: "chrismo", last_name: nil, age: nil, custom_attributes: {:instrument=>"piano", :style=>"jazz"}>
|
52
|
+
> p2 = Person.create(first_name: 'romer', custom_attributes: { hobby: 'games' })
|
53
|
+
=> #<Person:0x00007fac3ebcbb68 id: 2, first_name: "romer", last_name: nil, age: nil, custom_attributes: {:hobby=>"games"}>
|
54
|
+
> batch = [p1, p2].to_table
|
55
|
+
=> +----+------------+-----------+-----+--------+------------+--------+
|
56
|
+
| person | custom_attributes |
|
57
|
+
+----+------------+-----------+-----+--------+------------+--------+
|
58
|
+
| id | first_name | last_name | age | hobby | instrument | style |
|
59
|
+
+----+------------+-----------+-----+--------+------------+--------+
|
60
|
+
| 1 | chrismo | | | | piano | jazz |
|
61
|
+
| 2 | romer | | | games | | |
|
62
|
+
+----+------------+-----------+-----+--------+------------+--------+
|
63
|
+
```
|
64
|
+
|
65
|
+
### In a Script
|
66
|
+
|
67
|
+
`puts` won't work because of how Kernel#puts has special case code for Arrays.
|
68
|
+
Tablesmith::Table subclasses Array, so it can't cope with puts. Try to remember
|
69
|
+
to use `print` instead.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
require 'tablesmith'
|
73
|
+
|
74
|
+
print [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table
|
75
|
+
```
|
76
|
+
|
77
|
+
### CSV Support
|
78
|
+
```
|
79
|
+
> puts [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table.to_csv
|
80
|
+
date,amt
|
81
|
+
1/1/2020,35
|
82
|
+
1/2/2020,80
|
83
|
+
```
|
84
|
+
|
85
|
+
### HTML Support
|
86
|
+
```
|
87
|
+
> puts [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table.to_html
|
88
|
+
<table>
|
89
|
+
<thead>
|
90
|
+
<tr>
|
91
|
+
<th>date</th>
|
92
|
+
<th>amt</th>
|
93
|
+
</tr>
|
94
|
+
</thead>
|
95
|
+
<tbody>
|
96
|
+
<tr>
|
97
|
+
<td>1/1/2020</td>
|
98
|
+
<td>35</td>
|
99
|
+
</tr>
|
100
|
+
<tr>
|
101
|
+
<td>1/2/2020</td>
|
102
|
+
<td>80</td>
|
103
|
+
</tr>
|
104
|
+
</tbody>
|
105
|
+
</table>
|
106
|
+
```
|
107
|
+
|
108
|
+
## Troubleshooting
|
109
|
+
|
110
|
+
If you ever get a default inspection output in a console for a table, an
|
111
|
+
exception has likely occurred and been caught by IRB or Pry. Call
|
112
|
+
`.to_table.to_s` to see what the exception is.
|
113
|
+
|
114
|
+
```
|
115
|
+
[1] pry(main)> [1, [2, 3]].to_table
|
116
|
+
=> #<Tablesmith::Table:0x3fc083e14294>
|
117
|
+
[2] pry(main)> [1, [2, 3]].to_table.to_s
|
118
|
+
IndexError: element size differs (2 should be 1)
|
119
|
+
from /Users/chrismo/.bundle/ruby/2.6.0/gems/text-table-1.2.4/lib/text-table/table.rb:157:in `transpose'
|
120
|
+
```
|
22
121
|
|
23
122
|
## Why Not #{other_gem}?
|
24
123
|
|
25
|
-
Happy to learn about something else already out there, but have struggled to
|
26
|
-
that doesn't require some sort of setup. I want drop-in
|
27
|
-
Arrays and ActiveRecord objects.
|
124
|
+
Happy to learn about something else already out there, but I have struggled to
|
125
|
+
find something that doesn't require some sort of setup. I want drop-in
|
126
|
+
ready-to-go table output for Arrays, Hashes, and ActiveRecord objects.
|
28
127
|
|
29
|
-
Here's a quick list of other gems that I've tried out that are awesome and do
|
30
|
-
but don't seem to specialize in what I
|
128
|
+
Here's a quick list of other gems that I've tried out that are awesome and do
|
129
|
+
much more than what Tablesmith does, but don't seem to specialize in what I
|
130
|
+
want:
|
31
131
|
|
32
|
-
-
|
33
|
-
-
|
34
|
-
- table_print
|
35
|
-
- awesome_print
|
132
|
+
- [text-table](https://github.com/aptinio/text-table) _Tablesmith uses text-table underneath_
|
133
|
+
- [Hirb](https://github.com/cldwalker/hirb) _Hirb is cool, and pretty close to what I want_
|
134
|
+
- [table_print](http://tableprintgem.com/)
|
135
|
+
- [awesome_print](https://github.com/awesome-print/awesome_print)
|
136
|
+
- [tabulo](https://github.com/matt-harvey/tabulo)
|
data/Rakefile
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec/core/rake_task'
|
2
4
|
require 'bundler/gem_tasks'
|
3
5
|
|
4
|
-
FileList['tasks/*.rake'].each
|
6
|
+
FileList['tasks/*.rake'].each(&method(:load))
|
5
7
|
|
6
|
-
task :
|
8
|
+
task default: :spec
|
7
9
|
|
8
10
|
desc 'Run the specs.'
|
9
11
|
RSpec::Core::RakeTask.new do |t|
|
data/lib/tablesmith.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tablesmith::ActiveRecordSource
|
2
4
|
include Tablesmith::HashRowsBase
|
3
5
|
|
@@ -37,7 +39,7 @@ module Tablesmith::ActiveRecordSource
|
|
37
39
|
end
|
38
40
|
|
39
41
|
include.each do |association, opts|
|
40
|
-
ar_class = first.class.reflections[association].klass
|
42
|
+
ar_class = first.class.reflections[association.to_s].klass
|
41
43
|
process_columns(opts, ar_class)
|
42
44
|
end
|
43
45
|
end
|
@@ -73,7 +75,7 @@ module Tablesmith::ActiveRecordSource
|
|
73
75
|
def flatten_inner_hashes(hash)
|
74
76
|
new_hash = {}
|
75
77
|
stack = hash.each_pair.to_a
|
76
|
-
while ary = stack.shift
|
78
|
+
while (ary = stack.shift)
|
77
79
|
key, value = ary
|
78
80
|
if value.is_a?(Hash)
|
79
81
|
value.each_pair do |assoc_key, assoc_value|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Tablesmith::ArrayRowsSource
|
2
4
|
def text_table
|
3
5
|
build_columns if columns.nil?
|
@@ -11,7 +13,7 @@ module Tablesmith::ArrayRowsSource
|
|
11
13
|
# TODO: no support for deep
|
12
14
|
def build_columns
|
13
15
|
@columns ||= []
|
14
|
-
|
16
|
+
map do |array_row|
|
15
17
|
@columns << array_row.map { |item| Tablesmith::Column.new(name: item) }
|
16
18
|
end
|
17
19
|
@columns.flatten!
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# ActiveRecord and HashRowsSource share a lot, but not everything.
|
2
4
|
module Tablesmith::HashRowsBase
|
3
5
|
# not all resulting rows will have data in all columns, so make sure all rows pad out missing columns
|
@@ -8,6 +10,7 @@ module Tablesmith::HashRowsBase
|
|
8
10
|
|
9
11
|
def sort_columns(rows)
|
10
12
|
return if column_order.empty?
|
13
|
+
|
11
14
|
rows.map! do |row|
|
12
15
|
# this sort gives preference to column_order then falls back to alphabetic for leftovers.
|
13
16
|
# this is handy when columns auto-generate based on hash data.
|
@@ -32,4 +35,4 @@ module Tablesmith::HashRowsBase
|
|
32
35
|
column_names = rows.first.map(&:first)
|
33
36
|
grouped_headers(column_names) + [apply_column_aliases(column_names), :separator]
|
34
37
|
end
|
35
|
-
end
|
38
|
+
end
|