tablesmith 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|