tablesmith 0.4.0 → 0.6.2

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
- 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