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