tablesmith 0.4.1 → 0.5.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 +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
|