tablesmith 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -3
- data/Appraisals +2 -0
- data/README.md +13 -1
- data/Rakefile +6 -0
- data/gemfiles/activerecord_4.gemfile +6 -4
- data/gemfiles/activerecord_5.1.gemfile +6 -4
- data/gemfiles/activerecord_5.2.gemfile +6 -4
- data/gemfiles/activerecord_6.0.gemfile +6 -4
- data/lib/tablesmith.rb +1 -0
- data/lib/tablesmith/delegated_array_class.rb +39 -0
- data/lib/tablesmith/table.rb +22 -11
- data/lib/tablesmith/version.rb +1 -1
- data/spec/array_table_spec.rb +15 -7
- data/spec/table_spec.rb +10 -5
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3c75c62ab94384c394373d395134e52bbb21e4e94f8cc94646f450ada1f9678
|
4
|
+
data.tar.gz: 9aa2c83212ca484555bd5f7344e38e0ddc7b603315e2f976ff29e6054bb571bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0b940e2db92a0941ed25daaf81f501bec3d13964e1769f4d582a2966d76674ab151b6576010929ee2028f01e02e9fbdd10de0e526e7a7c0d26680f31193b1ee
|
7
|
+
data.tar.gz: 949d1f0e968bb9f4c8315508e755ba596736e9cb68dc037f5c06bbce3303e2062ac235e942f32b44a8ca9943b2961a42846270847dab18cb3a1b62a0e3ae32d1
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require:
|
2
|
-
- rubocop_lineup
|
3
|
-
|
4
1
|
AllCops:
|
5
2
|
TargetRubyVersion: 2.3
|
6
3
|
|
@@ -54,6 +51,9 @@ Layout/ClassStructure:
|
|
54
51
|
Layout/DotPosition:
|
55
52
|
EnforcedStyle: trailing
|
56
53
|
|
54
|
+
Layout/SpaceInsideHashLiteralBraces:
|
55
|
+
Enabled: false
|
56
|
+
|
57
57
|
Lint/Void:
|
58
58
|
Exclude:
|
59
59
|
- 'spec/**'
|
@@ -89,6 +89,9 @@ Metrics/MethodLength:
|
|
89
89
|
CountComments: false # count full line comments?
|
90
90
|
Max: 15
|
91
91
|
|
92
|
+
Naming/UncommunicativeMethodParamName:
|
93
|
+
Enabled: false
|
94
|
+
|
92
95
|
Rails/Date:
|
93
96
|
Enabled: true
|
94
97
|
EnforcedStyle: flexible
|
data/Appraisals
CHANGED
data/README.md
CHANGED
@@ -39,13 +39,25 @@ require 'tablesmith'
|
|
39
39
|
| 1 | 2 |
|
40
40
|
+---+---+
|
41
41
|
|
42
|
-
> [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table
|
42
|
+
> t = [{date: '1/1/2020', amt: 35}, {date: '1/2/2020', amt: 80}].to_table
|
43
43
|
=> +----------+-----+
|
44
44
|
| date | amt |
|
45
45
|
+----------+-----+
|
46
46
|
| 1/1/2020 | 35 |
|
47
47
|
| 1/2/2020 | 80 |
|
48
48
|
+----------+-----+
|
49
|
+
|
50
|
+
> # Table delegates to Array, all Array methods are available.
|
51
|
+
> t.select! { |h| h[:amt] > 40 }
|
52
|
+
=> [{:date=>"1/2/2020", :amt=>80}]
|
53
|
+
|
54
|
+
> t
|
55
|
+
=> +----------+-----+
|
56
|
+
| date | amt |
|
57
|
+
+----------+-----+
|
58
|
+
| 1/2/2020 | 80 |
|
59
|
+
+----------+-----+
|
60
|
+
|
49
61
|
|
50
62
|
> p1 = Person.create(first_name: 'chrismo', custom_attributes: { instrument: 'piano', style: 'jazz' })
|
51
63
|
=> #<Person:0x00007fac3eb406a8 id: 1, first_name: "chrismo", last_name: nil, age: nil, custom_attributes: {:instrument=>"piano", :style=>"jazz"}>
|
data/Rakefile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file was generated by Appraisal
|
2
4
|
|
3
|
-
source
|
5
|
+
source 'https://rubygems.org'
|
4
6
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
+
gem 'activerecord', '~> 4.0'
|
8
|
+
gem 'sqlite3', '~> 1.3.6'
|
7
9
|
|
8
|
-
gemspec path:
|
10
|
+
gemspec path: '../'
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file was generated by Appraisal
|
2
4
|
|
3
|
-
source
|
5
|
+
source 'https://rubygems.org'
|
4
6
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
+
gem 'activerecord', '~> 5.1.0'
|
8
|
+
gem 'sqlite3', '~> 1.4'
|
7
9
|
|
8
|
-
gemspec path:
|
10
|
+
gemspec path: '../'
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file was generated by Appraisal
|
2
4
|
|
3
|
-
source
|
5
|
+
source 'https://rubygems.org'
|
4
6
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
+
gem 'activerecord', '~> 5.2.0'
|
8
|
+
gem 'sqlite3', '~> 1.4'
|
7
9
|
|
8
|
-
gemspec path:
|
10
|
+
gemspec path: '../'
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file was generated by Appraisal
|
2
4
|
|
3
|
-
source
|
5
|
+
source 'https://rubygems.org'
|
4
6
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
+
gem 'activerecord', '~> 6.0.0'
|
8
|
+
gem 'sqlite3', '~> 1.4'
|
7
9
|
|
8
|
-
gemspec path:
|
10
|
+
gemspec path: '../'
|
data/lib/tablesmith.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tablesmith
|
4
|
+
# This adjustment to `DelegateClass(Array)` is necessary to allow calling puts
|
5
|
+
# on a `Tablesmith::Table` and still get the table output, rather than the
|
6
|
+
# default puts output of the underlying `Array`.
|
7
|
+
#
|
8
|
+
# Explaining why requires breaking some things down.
|
9
|
+
#
|
10
|
+
# The implementation of `Kernel::puts` has special code for an `Array`. The
|
11
|
+
# code inside `rb_io_puts` (in io.c) first checks to see if the object passed
|
12
|
+
# to it is a `String`. If not, it then calls `io_puts_ary`, which in turn
|
13
|
+
# calls `rb_check_array_type`. If `rb_check_array_type` confirms the passed
|
14
|
+
# object is an `Array`, then `io_puts_ary` loops over the elements of the
|
15
|
+
# `Array` and passes it to `rb_io_puts`. If the `Array` check fails in the
|
16
|
+
# original `rb_io_puts`, `rb_obj_as_string` is used.
|
17
|
+
#
|
18
|
+
# Early versions of `Tablesmith::Table` subclassed `Array`, but even after
|
19
|
+
# changing `Tablesmith::Table` to use any of the `Delegator` options, the code
|
20
|
+
# in `rb_check_array_type` still detected `Tablesmith::Table` as an `Array`.
|
21
|
+
# How does it do this?
|
22
|
+
#
|
23
|
+
# `rb_check_array_type` calls:
|
24
|
+
#
|
25
|
+
# `return rb_check_convert_type_with_id(ary, T_ARRAY, "Array", idTo_ary);`
|
26
|
+
#
|
27
|
+
# If a straight up type check fails, then it attempts to convert the object to
|
28
|
+
# an `Array` via the `to_ary` method.
|
29
|
+
#
|
30
|
+
# And wha-lah. We simply need to undefine the `to_ary` method added to
|
31
|
+
# `Tablesmith::Table` by `DelegateClass(Array)` and `rb_io_puts` will no
|
32
|
+
# longer output `Table` as an `Array` and will use its `to_s` method, the same
|
33
|
+
# as `print`.
|
34
|
+
def self.delegated_array_class
|
35
|
+
DelegateClass(Array).tap do |klass|
|
36
|
+
klass.undef_method(:to_ary)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/tablesmith/table.rb
CHANGED
@@ -4,17 +4,30 @@ require 'text-table'
|
|
4
4
|
require 'csv'
|
5
5
|
|
6
6
|
module Tablesmith
|
7
|
-
class Table <
|
7
|
+
class Table < Tablesmith.delegated_array_class
|
8
|
+
def initialize(array = [])
|
9
|
+
super(array)
|
10
|
+
@array = array
|
11
|
+
end
|
12
|
+
|
8
13
|
def method_missing(meth_id, *args)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
# In order to support `Kernel::puts` of a `Table`, we need to ignore
|
15
|
+
# `to_ary` calls here as well. See comments on `delegated_array_class`.
|
16
|
+
#
|
17
|
+
# While `DelegatorClass(Array)` proactively defines methods on `Table`
|
18
|
+
# that come from `Array`, it _also_ will pass calls through method_missing
|
19
|
+
# to the target object if it says it will respond to it.
|
20
|
+
#
|
21
|
+
# It seems a little redundant, but it is what it is, and so we must also
|
22
|
+
# cut off calls to `to_ary` in both places.
|
23
|
+
return nil if meth_id.to_sym == :to_ary
|
24
|
+
|
25
|
+
super
|
15
26
|
end
|
16
27
|
|
17
|
-
def respond_to_missing?
|
28
|
+
def respond_to_missing?(meth_id, _include_all)
|
29
|
+
return false if meth_id.to_sym == :to_ary
|
30
|
+
|
18
31
|
super
|
19
32
|
end
|
20
33
|
|
@@ -118,9 +131,7 @@ module Tablesmith
|
|
118
131
|
else
|
119
132
|
row = []
|
120
133
|
# this relies on Ruby versions where hash retains add order
|
121
|
-
groups.
|
122
|
-
row << { value: name, align: :center, colspan: span }
|
123
|
-
end
|
134
|
+
groups.each { |name, span| row << {value: name, align: :center, colspan: span} }
|
124
135
|
[row, :separator]
|
125
136
|
end
|
126
137
|
end
|
data/lib/tablesmith/version.rb
CHANGED
data/spec/array_table_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe 'Array Source' do
|
|
14
14
|
[%w[a b c], %w[d e f]].to_table.to_s.should == expected
|
15
15
|
end
|
16
16
|
|
17
|
-
def do_just_works_test(
|
17
|
+
def do_just_works_test(meth_id)
|
18
18
|
orig_stdout = $stdout
|
19
19
|
sio = StringIO.new
|
20
20
|
$stdout = sio
|
@@ -33,7 +33,7 @@ describe 'Array Source' do
|
|
33
33
|
+---+---+---+
|
34
34
|
TABLE
|
35
35
|
|
36
|
-
actual = do_just_works_test(
|
36
|
+
actual = do_just_works_test(meth_id)
|
37
37
|
actual.should == expected
|
38
38
|
end
|
39
39
|
|
@@ -42,14 +42,22 @@ describe 'Array Source' do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'just works with puts' do
|
45
|
-
pending
|
46
|
-
|
47
|
-
# Kernel.puts has special behavior for puts with Array,
|
48
|
-
# which Table subclasses, so this isn't going to work,
|
49
|
-
# unless we can stop subclassing Array.
|
50
45
|
just_works(:puts)
|
51
46
|
end
|
52
47
|
|
48
|
+
it 'just works with p' do
|
49
|
+
expected = <<~TABLE
|
50
|
+
+---+---+---+
|
51
|
+
| a | b | c |
|
52
|
+
+---+---+---+
|
53
|
+
| d | e | f |
|
54
|
+
+---+---+---+
|
55
|
+
TABLE
|
56
|
+
|
57
|
+
actual = do_just_works_test(:p)
|
58
|
+
actual.should == "#{expected}\n"
|
59
|
+
end
|
60
|
+
|
53
61
|
it 'just works with inspect' do
|
54
62
|
expected = <<~TABLE
|
55
63
|
+---+---+---+
|
data/spec/table_spec.rb
CHANGED
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
include Tablesmith # rubocop:disable Style/MixinUsage:
|
6
6
|
|
7
7
|
describe Table do
|
8
|
-
it 'should
|
8
|
+
it 'should delegate to the internal array' do
|
9
9
|
b = Table.new
|
10
10
|
b.length.should == 0
|
11
11
|
b << 1
|
@@ -15,12 +15,17 @@ describe Table do
|
|
15
15
|
b.class.should == Table
|
16
16
|
end
|
17
17
|
|
18
|
-
it 'should pass unmatched Array messages to all items' do
|
18
|
+
it 'should no longer pass unmatched Array messages to all items' do
|
19
|
+
# earlier pre-1.0 versions implemented method_missing in order to provide
|
20
|
+
# syntactic sugar for calling map on the underlying Array. But as time went
|
21
|
+
# on, it felt too heavy-handed and not worth it.
|
22
|
+
|
19
23
|
b = Table.new
|
20
24
|
b.length.should == 0
|
21
25
|
b << 1
|
22
26
|
b << '2'
|
23
|
-
b.to_i.should == [1, 2]
|
27
|
+
b.map(&:to_i).should == [1, 2]
|
28
|
+
-> { b.to_i }.should raise_error(NoMethodError)
|
24
29
|
end
|
25
30
|
|
26
31
|
it 'should handle empty Array' do
|
@@ -29,7 +34,7 @@ describe Table do
|
|
29
34
|
| (empty) |
|
30
35
|
+---------+
|
31
36
|
TEXT
|
32
|
-
[].to_table.
|
37
|
+
[].to_table.to_s.should == expected
|
33
38
|
end
|
34
39
|
|
35
40
|
it 'should handle a simple two row Array' do
|
@@ -42,7 +47,7 @@ describe Table do
|
|
42
47
|
| d | e | f |
|
43
48
|
+---+---+---+
|
44
49
|
TABLE
|
45
|
-
actual.to_table.
|
50
|
+
actual.to_table.to_s.should == expected
|
46
51
|
end
|
47
52
|
|
48
53
|
it 'should output csv' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tablesmith
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chrismo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: text-table
|
@@ -190,6 +190,7 @@ files:
|
|
190
190
|
- lib/tablesmith.rb
|
191
191
|
- lib/tablesmith/active_record_source.rb
|
192
192
|
- lib/tablesmith/array_rows_source.rb
|
193
|
+
- lib/tablesmith/delegated_array_class.rb
|
193
194
|
- lib/tablesmith/hash_rows_base.rb
|
194
195
|
- lib/tablesmith/hash_rows_source.rb
|
195
196
|
- lib/tablesmith/html_formatter.rb
|