tablesmith 0.4.0 → 0.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 96ab0a18c776e80aa103908884db53eb98cf7a89
4
- data.tar.gz: a645ccf65e779cd8b5311b7bd6429d3a48ea752d
2
+ SHA256:
3
+ metadata.gz: e087948276046a5d4ca9af901465ce4afe11c627acd172b1be29d6a46e018672
4
+ data.tar.gz: 1f366c3de38e86d801d38a8f1356fa76f11d6b71eb5b5d1c8df59331be3dafcc
5
5
  SHA512:
6
- metadata.gz: 8e1d90632da2e260c393346d9a4a230dc747bdf1820ab3a95243efd612ad14f6578ba0ae6062300d1685f3dc811617d5c65eaa0e93caca67c37ad7739570985f
7
- data.tar.gz: 5162cfc4edc75df6c4019333a87ecd3b867f57f923b9b13cd96b7c6952880cd4202c01cce5a2e145e697eaaec5e3a94c9e31aa5f49ab774dcac8bd64149e781d
6
+ metadata.gz: b2f5bd5a0c206007be448a651aaf9de768615d526640c0bf3edd760b3e369303da06554aa18cc304faaf4d2940a9dfa824a25a0bbba06f4273e2b6680fb785a2
7
+ data.tar.gz: effe9b8dcfaa3d1f747006aa05af31d4eb92586af0ab358a17e36ece76b019cc2698178af52a98bd219b3366af1e8051c7c0a012b915fa7da33793bb314e82ad
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tablesmith/delegated_array_class'
1
4
  require 'tablesmith/table'
2
5
  require 'tablesmith/array_rows_source'
3
6
  require 'tablesmith/hash_rows_base'
@@ -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
- self.map do |array_row|
16
+ map do |array_row|
15
17
  @columns << array_row.map { |item| Tablesmith::Column.new(name: item) }
16
18
  end
17
19
  @columns.flatten!
@@ -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
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tablesmith::HashRowsSource
2
4
  include Tablesmith::HashRowsBase
3
5
 
@@ -11,7 +13,7 @@ module Tablesmith::HashRowsSource
11
13
  end
12
14
 
13
15
  def flatten_hash_to_row(deep_hash, columns)
14
- row = ActiveSupport::OrderedHash.new
16
+ row = {}
15
17
  columns.each do |col_or_hash|
16
18
  value_from_hash(row, deep_hash, col_or_hash)
17
19
  end
@@ -21,9 +23,9 @@ module Tablesmith::HashRowsSource
21
23
  # TODO: no support for deep
22
24
  def build_columns
23
25
  @columns ||= []
24
- self.map do |hash_row|
26
+ map do |hash_row|
25
27
  @columns << hash_row.keys.map { |k| Tablesmith::Column.new(name: k) }
26
- end
28
+ end
27
29
  @columns.flatten!
28
30
  end
29
31
 
@@ -37,11 +39,9 @@ module Tablesmith::HashRowsSource
37
39
  value_from_hash(row, deep_hash[sub_hash_key], inner_col_or_hash)
38
40
  end
39
41
  end
40
- else
41
- nil
42
42
  end
43
- rescue => e
44
- $stderr.puts "#{e.message}: #{col_or_hash}" if @debug
43
+ rescue StandardError => e
44
+ warn "#{e.message}: #{col_or_hash}" if @debug
45
45
  end
46
46
 
47
47
  def hash_rows_to_text_table(hash_rows)
@@ -60,6 +60,6 @@ module Tablesmith::HashRowsSource
60
60
  end
61
61
 
62
62
  # Array addition from text-table
63
- table.to_table(:first_row_is_head => true)
63
+ table.to_table(first_row_is_head: true)
64
64
  end
65
65
  end
@@ -21,34 +21,32 @@ class HtmlFormatter
21
21
 
22
22
  def append_table_head
23
23
  @lines << "#{indent}<thead>"
24
- @lines << "#{indent}<tr>"
25
24
  unless @table.empty?
26
25
  rows = @table.text_table.rows[0..0]
27
26
  append_rows(rows, 'th')
28
27
  end
29
- @lines << "#{indent}</tr>"
30
28
  @lines << "#{indent}</thead>"
31
29
  end
32
30
 
33
31
  def append_table_body
34
32
  @lines << "#{indent}<tbody>"
35
- @lines << "#{indent}<tr>"
36
-
37
33
  unless @table.empty?
38
34
  rows = @table.text_table.rows[2..-1]
39
35
  append_rows(rows, 'td')
40
36
  end
41
- @lines << "#{indent}</tr>"
42
37
  @lines << "#{indent}</tbody>"
43
38
  end
44
39
 
45
40
  def append_rows(rows, tag)
46
41
  rows.each do |row|
47
42
  next if row == :separator
43
+
44
+ @lines << "#{indent}<tr>"
48
45
  row.map do |cell|
49
46
  value = cell_value(cell)
50
47
  @lines << "#{indent}#{indent}<#{tag}>#{value}</#{tag}>"
51
48
  end
49
+ @lines << "#{indent}</tr>"
52
50
  end
53
51
  end
54
52
 
@@ -1,21 +1,40 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'text-table'
2
4
  require 'csv'
3
5
 
4
6
  module Tablesmith
5
- class Table < Array
7
+ class Table < Tablesmith.delegated_array_class
8
+ def initialize(array = [])
9
+ super(array)
10
+ @array = array
11
+ end
12
+
6
13
  def method_missing(meth_id, *args)
7
- count = 1
8
- self.map do |t|
9
- $stderr.print '.' if count.divmod(100)[1] == 0
10
- count += 1
11
- t.send(meth_id, *args)
12
- end
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
13
26
  end
14
27
 
15
- def respond_to_missing?
28
+ def respond_to_missing?(meth_id, _include_all)
29
+ return false if meth_id.to_sym == :to_ary
30
+
16
31
  super
17
32
  end
18
33
 
34
+ def to_s
35
+ text_table.to_s
36
+ end
37
+
19
38
  # irb
20
39
  def inspect
21
40
  pretty_inspect
@@ -32,9 +51,9 @@ module Tablesmith
32
51
  end
33
52
 
34
53
  def text_table
35
- return ['(empty)'].to_text_table if self.empty?
54
+ return ['(empty)'].to_text_table if empty?
36
55
 
37
- rows = self.map { |item| convert_item_to_hash_row(item) }.compact
56
+ rows = map { |item| convert_item_to_hash_row(item) }.compact
38
57
 
39
58
  normalize_keys(rows)
40
59
 
@@ -48,12 +67,13 @@ module Tablesmith
48
67
  CSV.generate do |csv|
49
68
  text_table.rows.each do |row|
50
69
  next if row == :separator
70
+
51
71
  csv << row.map do |cell|
52
72
  case cell
53
- when Hash
54
- cell[:value]
55
- else
56
- cell
73
+ when Hash
74
+ cell[:value]
75
+ else
76
+ cell
57
77
  end
58
78
  end
59
79
  end
@@ -70,8 +90,7 @@ module Tablesmith
70
90
  end
71
91
 
72
92
  # override in subclass or mixin
73
- def sort_columns(rows)
74
- end
93
+ def sort_columns(rows); end
75
94
 
76
95
  # override in subclass or mixin
77
96
  def convert_item_to_hash_row(item)
@@ -79,22 +98,24 @@ module Tablesmith
79
98
  end
80
99
 
81
100
  # override in subclass or mixin
82
- def normalize_keys(rows)
83
- end
101
+ def normalize_keys(rows); end
84
102
 
85
103
  # override in subclass or mixin
86
104
  def column_order
87
105
  []
88
106
  end
89
107
 
90
- def columns
91
- @columns
92
- end
108
+ attr_reader :columns
93
109
 
94
110
  def create_headers(rows)
95
- top_row = rows.first
96
- column_names = top_row.first.is_a?(Array) ? top_row.map(&:first) : top_row
97
- grouped_headers(column_names) + [apply_column_aliases(column_names), :separator]
111
+ first_element = rows.first
112
+ if first_element.is_a?(Array)
113
+ top_row = first_element
114
+ column_names = top_row.first.is_a?(Array) ? top_row.map(&:first) : top_row
115
+ grouped_headers(column_names) + [apply_column_aliases(column_names), :separator]
116
+ else
117
+ []
118
+ end
98
119
  end
99
120
 
100
121
  def grouped_headers(column_names)
@@ -110,9 +131,7 @@ module Tablesmith
110
131
  else
111
132
  row = []
112
133
  # this relies on Ruby versions where hash retains add order
113
- groups.each_pair do |name, span|
114
- row << {value: name, align: :center, colspan: span}
115
- end
134
+ groups.each { |name, span| row << {value: name, align: :center, colspan: span} }
116
135
  [row, :separator]
117
136
  end
118
137
  end
@@ -121,7 +140,7 @@ module Tablesmith
121
140
  column_names.map do |name|
122
141
  instance = columns.detect { |ca| ca.name.to_s == name.to_s }
123
142
  value = instance ? instance.display_name : name
124
- {:value => value, :align => :center}
143
+ { value: value, align: :center }
125
144
  end
126
145
  end
127
146
  end
@@ -129,14 +148,14 @@ module Tablesmith
129
148
  class Column
130
149
  attr_accessor :source, :name, :alias
131
150
 
132
- def initialize(attributes={})
151
+ def initialize(attributes = {})
133
152
  @source = attributes.delete(:source)
134
153
  @name = attributes.delete(:name)
135
154
  @alias = attributes.delete(:alias)
136
155
  end
137
156
 
138
157
  def display_name
139
- "#{@alias || @name}"
158
+ (@alias || @name).to_s
140
159
  end
141
160
 
142
161
  def full_unaliased_name
@@ -157,18 +176,12 @@ class Array
157
176
  # so mixed content could be supported. Maybe every cell could be
158
177
  # rendered appropriately, with nested tables.
159
178
  if defined?(ActiveRecord) && defined?(ActiveRecord::Base)
160
- if b.first && b.first.is_a?(ActiveRecord::Base)
161
- b.extend Tablesmith::ActiveRecordSource
162
- end
179
+ b.extend Tablesmith::ActiveRecordSource if b.first&.is_a?(ActiveRecord::Base)
163
180
  end
164
181
 
165
- if b.first && b.first.is_a?(Hash)
166
- b.extend Tablesmith::HashRowsSource
167
- end
182
+ b.extend Tablesmith::HashRowsSource if b.first&.is_a?(Hash)
168
183
 
169
- if b.first && b.first.is_a?(Array)
170
- b.extend Tablesmith::ArrayRowsSource
171
- end
184
+ b.extend Tablesmith::ArrayRowsSource if b.first&.is_a?(Array)
172
185
 
173
186
  b
174
187
  end
@@ -179,4 +192,4 @@ class Hash
179
192
  b = Tablesmith::Table.new([self])
180
193
  b.extend Tablesmith::HashRowsSource
181
194
  end
182
- end
195
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tablesmith
2
- VERSION = '0.4.0'.freeze
4
+ VERSION = '0.6.2'
3
5
  end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
5
+ # rubocop:disable Rails/SkipsModelValidations
3
6
  describe 'ActiveRecordSource' do
4
7
  it 'outputs text table of multiple ActiveRecords' do
5
8
  a = Person.new.tap { |c| c.first_name = 'A' }
@@ -12,11 +15,11 @@ describe 'ActiveRecordSource' do
12
15
  | | B | | | |
13
16
  +----+------------+-----------+-----+-------------------+
14
17
  TABLE
15
- [a, b].to_table.text_table.to_s.should == expected
18
+ [a, b].to_table.to_s.should == expected
16
19
  end
17
20
 
18
21
  it 'outputs ActiveRecord in column order' do
19
- p = Person.create(:first_name => 'chris', :last_name => 'mo', :age => 43)
22
+ p = Person.create(first_name: 'chris', last_name: 'mo', age: 43)
20
23
  expected = <<~TABLE
21
24
  +----+------------+-----------+-----+-------------------+
22
25
  | id | first_name | last_name | age | custom_attributes |
@@ -24,11 +27,11 @@ describe 'ActiveRecordSource' do
24
27
  | 1 | chris | mo | 43 | |
25
28
  +----+------------+-----------+-----+-------------------+
26
29
  TABLE
27
- [p].to_table.text_table.to_s.should == expected
30
+ [p].to_table.to_s.should == expected
28
31
  end
29
32
 
30
33
  it 'handles custom serialization options in batch' do
31
- p = Person.create(:first_name => 'chrismo', :age => 43)
34
+ p = Person.create(first_name: 'chrismo', age: 43)
32
35
 
33
36
  expected = <<~TABLE
34
37
  +------------+-----+-----------+
@@ -40,14 +43,14 @@ describe 'ActiveRecordSource' do
40
43
  b = [p].to_table
41
44
 
42
45
  def b.serializable_options
43
- {:only => [:first_name, :age], :methods => [:year_born]}
46
+ { only: %i[first_name age], methods: [:year_born] }
44
47
  end
45
48
 
46
- b.text_table.to_s.should == expected
49
+ b.to_s.should == expected
47
50
  end
48
51
 
49
52
  it 'auto reloads records' do
50
- p = Person.create(:first_name => 'chrismo', :age => 43)
53
+ p = Person.create(first_name: 'chrismo', age: 43)
51
54
 
52
55
  expected = <<~TABLE
53
56
  +------------+-----+-----------+
@@ -59,9 +62,9 @@ describe 'ActiveRecordSource' do
59
62
  b = [p].to_table
60
63
 
61
64
  def b.serializable_options
62
- {:only => [:first_name, :age], :methods => [:year_born]}
65
+ { only: %i[first_name age], methods: [:year_born] }
63
66
  end
64
- b.text_table.to_s.should == expected
67
+ b.to_s.should == expected
65
68
 
66
69
  # update the value through another instance.
67
70
  Person.last.update_column(:age, 46)
@@ -73,11 +76,11 @@ describe 'ActiveRecordSource' do
73
76
  | chrismo | 46 | 1968 |
74
77
  +------------+-----+-----------+
75
78
  TABLE
76
- b.text_table.to_s.should == expected
79
+ b.to_s.should == expected
77
80
  end
78
81
 
79
82
  it 'handles column name partials' do
80
- p = Person.create(:first_name => 'chris', :last_name => 'mo', :age => 43)
83
+ p = Person.create(first_name: 'chris', last_name: 'mo', age: 43)
81
84
  expected = <<~TABLE
82
85
  +-------+------+-----+
83
86
  | first | last | age |
@@ -88,14 +91,14 @@ describe 'ActiveRecordSource' do
88
91
  b = [p].to_table
89
92
 
90
93
  def b.serializable_options
91
- {:only => [:first, :last, :age]}
94
+ { only: %i[first last age] }
92
95
  end
93
96
 
94
- b.text_table.to_s.should == expected
97
+ b.to_s.should == expected
95
98
  end
96
99
 
97
100
  it 'handles column name partials across words' do
98
- p = Person.create(:first_name => 'chris', :last_name => 'mo', :age => 43)
101
+ p = Person.create(first_name: 'chris', last_name: 'mo', age: 43)
99
102
  expected = <<~TABLE
100
103
  +--------+--------+-----+
101
104
  | f_name | l_name | age |
@@ -106,14 +109,14 @@ describe 'ActiveRecordSource' do
106
109
  b = [p].to_table
107
110
 
108
111
  def b.serializable_options
109
- {:only => [:f_name, :l_name, :age]}
112
+ { only: %i[f_name l_name age] }
110
113
  end
111
114
 
112
- b.text_table.to_s.should == expected
115
+ b.to_s.should == expected
113
116
  end
114
117
 
115
118
  it 'handles explicit column aliases' do
116
- p = Person.create(:first_name => 'chris', :last_name => 'mo', :age => 43)
119
+ p = Person.create(first_name: 'chris', last_name: 'mo', age: 43)
117
120
  expected = <<~TABLE
118
121
  +---------------+----------+-----+
119
122
  | primer_nombre | apellido | age |
@@ -129,10 +132,10 @@ describe 'ActiveRecordSource' do
129
132
  end
130
133
 
131
134
  def b.serializable_options
132
- {:only => [:first_name, :last_name, :age]}
135
+ { only: %i[first_name last_name age] }
133
136
  end
134
137
 
135
- b.text_table.to_s.should == expected
138
+ b.to_s.should == expected
136
139
  end
137
140
 
138
141
  it 'handles associations without aliases' do
@@ -141,7 +144,7 @@ describe 'ActiveRecordSource' do
141
144
  b = [s].to_table
142
145
 
143
146
  def b.serializable_options
144
- {:only => [:name], :include => {:account => {:only => [:name, :tax_identification_number]}}}
147
+ { only: [:name], include: { account: { only: %i[name tax_identification_number] } } }
145
148
  end
146
149
 
147
150
  expected = <<~TABLE
@@ -154,7 +157,7 @@ describe 'ActiveRecordSource' do
154
157
  +----------+---------+---------------------------+
155
158
  TABLE
156
159
 
157
- b.text_table.to_s.should == expected
160
+ b.to_s.should == expected
158
161
  end
159
162
 
160
163
  it 'handles associations with aliases' do
@@ -163,7 +166,7 @@ describe 'ActiveRecordSource' do
163
166
  b = [s].to_table
164
167
 
165
168
  def b.serializable_options
166
- {:only => [:name], :include => {:account => {:only => [:name, :tax_id]}}}
169
+ { only: [:name], include: { account: { only: %i[name tax_id] } } }
167
170
  end
168
171
 
169
172
  expected = <<~TABLE
@@ -176,7 +179,7 @@ describe 'ActiveRecordSource' do
176
179
  +----------+---------+--------+
177
180
  TABLE
178
181
 
179
- b.text_table.to_s.should == expected
182
+ b.to_s.should == expected
180
183
  end
181
184
 
182
185
  it 'retains serializable_options ordering'
@@ -187,7 +190,7 @@ describe 'ActiveRecordSource' do
187
190
 
188
191
  # may need/want to handle the hash resulting from an association differently from the hash resulting from a method/attr
189
192
  it 'supports field with hash contents' do
190
- p = Person.create(first_name: 'chrismo', custom_attributes: {skills: {instrument: 'piano', style: 'jazz'}})
193
+ p = Person.create(first_name: 'chrismo', custom_attributes: { skills: { instrument: 'piano', style: 'jazz' } })
191
194
  b = [p].to_table
192
195
 
193
196
  a = format_ids([p.id])[0]
@@ -201,12 +204,12 @@ describe 'ActiveRecordSource' do
201
204
  +----+------------+-----------+-----+----------------------------------------+
202
205
  TABLE
203
206
 
204
- b.text_table.to_s.should == expected
207
+ b.to_s.should == expected
205
208
  end
206
209
 
207
210
  it 'supports multiple rows with different column counts' do
208
- p2 = Person.create(first_name: 'romer', custom_attributes: {instrument: 'kazoo'})
209
- p1 = Person.create(first_name: 'chrismo', custom_attributes: {instrument: 'piano', style: 'jazz'})
211
+ p2 = Person.create(first_name: 'romer', custom_attributes: { instrument: 'kazoo' })
212
+ p1 = Person.create(first_name: 'chrismo', custom_attributes: { instrument: 'piano', style: 'jazz' })
210
213
  p3 = Person.create(first_name: 'glv', custom_attributes: {})
211
214
  batch = [p2, p1, p3].to_table
212
215
 
@@ -224,12 +227,12 @@ describe 'ActiveRecordSource' do
224
227
  +----+------------+-----------+-----+------------+-----------+
225
228
  TABLE
226
229
 
227
- batch.text_table.to_s.should == expected
230
+ batch.to_s.should == expected
228
231
  end
229
232
 
230
233
  it 'supports consistent ordering of dynamic columns' do
231
- p1 = Person.create(first_name: 'chrismo', custom_attributes: {instrument: 'piano', style: 'jazz'})
232
- p2 = Person.create(first_name: 'romer', custom_attributes: {hobby: 'games'})
234
+ p1 = Person.create(first_name: 'chrismo', custom_attributes: { instrument: 'piano', style: 'jazz' })
235
+ p2 = Person.create(first_name: 'romer', custom_attributes: { hobby: 'games' })
233
236
  batch = [p1, p2].to_table
234
237
 
235
238
  a, b = format_ids([p1.id, p2.id])
@@ -245,7 +248,7 @@ describe 'ActiveRecordSource' do
245
248
  +----+------------+-----------+-----+--------+------------+--------+
246
249
  TABLE
247
250
 
248
- batch.text_table.to_s.should == expected
251
+ batch.to_s.should == expected
249
252
  end
250
253
 
251
254
  it 'handles AR instance without an association present' do
@@ -253,7 +256,7 @@ describe 'ActiveRecordSource' do
253
256
  b = [s].to_table
254
257
 
255
258
  def b.serializable_options
256
- {:only => [:name], :include => {:account => {:only => [:name, :tax_id]}}}
259
+ { only: [:name], include: { account: { only: %i[name tax_id] } } }
257
260
  end
258
261
 
259
262
  expected = <<~TABLE
@@ -264,11 +267,11 @@ describe 'ActiveRecordSource' do
264
267
  +----------+
265
268
  TABLE
266
269
 
267
- b.text_table.to_s.should == expected
270
+ b.to_s.should == expected
268
271
  end
269
272
 
270
273
  it 'properly groups when original columns not sequential' do
271
- s2 = Supplier.create(name: 'sup. two', custom_attributes: {a: 1})
274
+ s2 = Supplier.create(name: 'sup. two', custom_attributes: { a: 1 })
272
275
 
273
276
  def s2.foo
274
277
  ''
@@ -278,7 +281,7 @@ describe 'ActiveRecordSource' do
278
281
 
279
282
  # methods need Columns as well
280
283
  def b.serializable_options
281
- {:only => [:name, :custom_attributes], :methods => [:foo]}
284
+ { only: %i[name custom_attributes], methods: [:foo] }
282
285
  end
283
286
 
284
287
  expected = <<~TABLE
@@ -291,12 +294,12 @@ describe 'ActiveRecordSource' do
291
294
  +----------+------+-------------------+
292
295
  TABLE
293
296
 
294
- b.text_table.to_s.should == expected
297
+ b.to_s.should == expected
295
298
  end
296
299
 
297
300
  it 'supports one to many association' do
298
301
  p = Parent.create(name: 'parent')
299
- c = Child.create(name: 'child', parent: p)
302
+ Child.create(name: 'child', parent: p)
300
303
 
301
304
  b = [p].to_table
302
305
 
@@ -310,32 +313,32 @@ describe 'ActiveRecordSource' do
310
313
  TABLE
311
314
 
312
315
  def b.serializable_options
313
- {:include => {:children => {:only => [:name]}}}
316
+ { include: { children: { only: [:name] } } }
314
317
  end
315
318
 
316
- b.text_table.to_s.should == expected
319
+ b.to_s.should == expected
317
320
  end
318
321
 
319
322
  def format_ids(ary)
320
- ary.map {|value| " #{value.to_s.ljust(3)}" }
323
+ ary.map { |value| " #{value.to_s.ljust(3)}" }
321
324
  end
322
325
 
323
326
  describe 'fold un-sourced attributes into source hash' do
324
327
  let(:obj) { Object.new.extend Tablesmith::ActiveRecordSource }
325
328
 
326
329
  it 'should handle simple hash' do
327
- obj.fold_un_sourced_attributes_into_source_hash(:foo, {a: 1, b: 2}).should == {foo: {a: 1, b: 2}}
330
+ obj.fold_un_sourced_attributes_into_source_hash(:foo, a: 1, b: 2).should == { foo: { a: 1, b: 2 } }
328
331
  end
329
332
 
330
333
  it 'should handle nested hashes' do
331
- before = {'name' => 'chris', account: {'name' => 'account_name'}}
332
- expected = {foo: {'name' => 'chris'}, account: {'name' => 'account_name'}}
334
+ before = { 'name' => 'chris', account: { 'name' => 'account_name' } }
335
+ expected = { foo: { 'name' => 'chris' }, account: { 'name' => 'account_name' } }
333
336
  obj.fold_un_sourced_attributes_into_source_hash(:foo, before).should == expected
334
337
  end
335
338
 
336
339
  it 'should handle deep nested hashes' do
337
- before = {'name' => 'chris', account: {'id' => {'name' => 'account_name', 'number' => 123456}}}
338
- expected = {foo: {'name' => 'chris'}, account: {'id' => {'name' => 'account_name', 'number' => 123456}}}
340
+ before = { 'name' => 'chris', account: { 'id' => { 'name' => 'account_name', 'number' => 123_456 } } }
341
+ expected = { foo: { 'name' => 'chris' }, account: { 'id' => { 'name' => 'account_name', 'number' => 123_456 } } }
339
342
  obj.fold_un_sourced_attributes_into_source_hash(:foo, before).should == expected
340
343
  end
341
344
  end
@@ -344,17 +347,18 @@ describe 'ActiveRecordSource' do
344
347
  let(:obj) { Object.new.extend Tablesmith::ActiveRecordSource }
345
348
 
346
349
  it 'should flatten inner hash' do
347
- before = {foo: {'name' => 'chris'}, account: {'name' => 'account_name'}}
348
- expected = {'foo.name' => 'chris', 'account.name' => 'account_name'}
350
+ before = { foo: { 'name' => 'chris' }, account: { 'name' => 'account_name' } }
351
+ expected = { 'foo.name' => 'chris', 'account.name' => 'account_name' }
349
352
 
350
353
  obj.flatten_inner_hashes(before).should == expected
351
354
  end
352
355
 
353
356
  it 'should to_s deep nested hashes' do
354
- before = {foo: {'name' => 'chris'}, account: {'id' => {'name' => 'account_name', 'number' => 123456}}}
355
- expected = {'foo.name' => 'chris', "account.id" => "{\"name\"=>\"account_name\", \"number\"=>123456}"}
357
+ before = { foo: { 'name' => 'chris' }, account: { 'id' => { 'name' => 'account_name', 'number' => 123_456 } } }
358
+ expected = { 'foo.name' => 'chris', 'account.id' => '{"name"=>"account_name", "number"=>123456}' }
356
359
 
357
360
  obj.flatten_inner_hashes(before).should == expected
358
361
  end
359
362
  end
360
363
  end
364
+ # rubocop:enable Rails/SkipsModelValidations