bumblebee 2.1.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -2
- data/.travis.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/README.md +172 -138
- data/bin/console +2 -6
- data/lib/bumblebee/bumblebee.rb +16 -62
- data/lib/bumblebee/column.rb +41 -63
- data/lib/bumblebee/column_dsl.rb +38 -0
- data/lib/bumblebee/column_set.rb +83 -0
- data/lib/bumblebee/converter.rb +97 -0
- data/lib/bumblebee/core_ext/hash.rb +21 -0
- data/lib/bumblebee/mutator.rb +54 -0
- data/lib/bumblebee/null_converter.rb +17 -0
- data/lib/bumblebee/object_interface.rb +66 -0
- data/lib/bumblebee/simple_converter.rb +109 -0
- data/lib/bumblebee/template.rb +23 -37
- data/lib/bumblebee/version.rb +1 -1
- data/spec/bumblebee/simple_converter_spec.rb +29 -0
- data/spec/bumblebee/template_spec.rb +151 -36
- data/spec/examples/converter_test_case.rb +113 -0
- data/spec/examples/person_template.rb +66 -0
- data/spec/examples/simple_object.rb +27 -0
- data/spec/fixtures/people/data.csv +3 -0
- data/spec/fixtures/people/data.yml +46 -0
- data/spec/fixtures/registrations/columns.yml +35 -0
- data/spec/fixtures/registrations/data.csv +3 -0
- data/spec/fixtures/registrations/data.yml +26 -0
- data/spec/fixtures/simple/columns.yml +4 -0
- data/spec/fixtures/{custom_readme_example.csv → simple/data.csv} +1 -1
- data/spec/fixtures/simple/data.yml +12 -0
- data/spec/spec_helper.rb +29 -3
- metadata +34 -10
- data/spec/bumblebee/bumblebee_spec.rb +0 -167
- data/spec/bumblebee/column_spec.rb +0 -213
- data/spec/fixtures/simple_readme_example.csv +0 -4
@@ -1,167 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
require './spec/spec_helper'
|
11
|
-
|
12
|
-
describe ::Bumblebee do
|
13
|
-
let(:columns) do
|
14
|
-
[
|
15
|
-
{ field: :name },
|
16
|
-
{ field: :dob }
|
17
|
-
]
|
18
|
-
end
|
19
|
-
|
20
|
-
let(:reverse_columns) do
|
21
|
-
[
|
22
|
-
{ field: :dob },
|
23
|
-
{ field: :name }
|
24
|
-
]
|
25
|
-
end
|
26
|
-
|
27
|
-
let(:people) do
|
28
|
-
[
|
29
|
-
{ name: 'Matt', dob: '1901-01-03' },
|
30
|
-
{ name: 'Nathan', dob: '1931-09-03' }
|
31
|
-
]
|
32
|
-
end
|
33
|
-
|
34
|
-
let(:csv) { "name,dob\nMatt,1901-01-03\nNathan,1931-09-03\n" }
|
35
|
-
|
36
|
-
let(:quoted_csv) { "\"name\",\"dob\"\n\"Matt\",\"1901-01-03\"\n\"Nathan\",\"1931-09-03\"\n" }
|
37
|
-
|
38
|
-
it 'should generate a csv using column argument' do
|
39
|
-
actual = Bumblebee.generate_csv(columns, people)
|
40
|
-
|
41
|
-
expect(actual).to eq(csv)
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'should generate a csv using block' do
|
45
|
-
actual = Bumblebee.generate_csv(people) do |t|
|
46
|
-
columns.each do |column|
|
47
|
-
t.column column[:field]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
expect(actual).to eq(csv)
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'should generate a csv and accept options' do
|
55
|
-
options = {
|
56
|
-
force_quotes: true
|
57
|
-
}
|
58
|
-
|
59
|
-
actual = ::Bumblebee.generate_csv(columns, people, options)
|
60
|
-
|
61
|
-
expect(actual).to eq(quoted_csv)
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should parse a csv using columns argument' do
|
65
|
-
objects = Bumblebee.parse_csv(columns, csv)
|
66
|
-
|
67
|
-
expect(objects).to eq(people)
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'should parse a csv using columns block' do
|
71
|
-
objects = Bumblebee.parse_csv(csv) do |t|
|
72
|
-
columns.each do |column|
|
73
|
-
t.column column[:field]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
expect(objects).to eq(people)
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should parse a csv with columns in different order than headers' do
|
81
|
-
objects = ::Bumblebee.parse_csv(reverse_columns, csv)
|
82
|
-
|
83
|
-
expect(objects).to eq(people)
|
84
|
-
end
|
85
|
-
|
86
|
-
describe 'README examples' do
|
87
|
-
describe 'the simple 1:1 parsing example' do
|
88
|
-
let(:data) { fixture('simple_readme_example.csv') }
|
89
|
-
|
90
|
-
let(:columns) do
|
91
|
-
[
|
92
|
-
{ field: 'id' },
|
93
|
-
{ field: 'name' },
|
94
|
-
{ field: 'dob' },
|
95
|
-
{ field: 'phone' }
|
96
|
-
]
|
97
|
-
end
|
98
|
-
|
99
|
-
let(:output) do
|
100
|
-
[
|
101
|
-
{ 'id' => '1', 'name' => 'Matt', 'dob' => '2/3/01', 'phone' => '555-555-5555' },
|
102
|
-
{ 'id' => '2', 'name' => 'Nick', 'dob' => '9/3/21', 'phone' => '444-444-4444' },
|
103
|
-
{ 'id' => '3', 'name' => 'Sam', 'dob' => '12/12/32', 'phone' => '333-333-3333' }
|
104
|
-
]
|
105
|
-
end
|
106
|
-
|
107
|
-
specify 'works as advertised' do
|
108
|
-
expect(Bumblebee.parse_csv(columns, data)).to eq output
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe 'the custom parsing example' do
|
113
|
-
let(:data) { fixture('custom_readme_example.csv') }
|
114
|
-
|
115
|
-
let(:columns) do
|
116
|
-
[
|
117
|
-
{
|
118
|
-
field: :id,
|
119
|
-
header: 'ID #',
|
120
|
-
to_object: ->(o) { o['ID #'].to_i }
|
121
|
-
},
|
122
|
-
{
|
123
|
-
field: :name,
|
124
|
-
header: 'First Name',
|
125
|
-
to_csv: %i[name first],
|
126
|
-
to_object: ->(o) { { first: o['First Name'] } }
|
127
|
-
},
|
128
|
-
{ field: :demo,
|
129
|
-
header: 'Date of Birth',
|
130
|
-
to_csv: %i[demo dob],
|
131
|
-
to_object: ->(o) { { dob: o['Date of Birth'] } } },
|
132
|
-
{ field: :contact,
|
133
|
-
header: 'Phone #',
|
134
|
-
to_csv: %i[contact phone],
|
135
|
-
to_object: ->(o) { { phone: o['Phone #'] } } }
|
136
|
-
]
|
137
|
-
end
|
138
|
-
|
139
|
-
let(:output) do
|
140
|
-
[
|
141
|
-
{
|
142
|
-
id: 1,
|
143
|
-
name: { first: 'Matt' },
|
144
|
-
demo: { dob: '1901-02-03' },
|
145
|
-
contact: { phone: '555-555-5555' }
|
146
|
-
},
|
147
|
-
{
|
148
|
-
id: 2,
|
149
|
-
name: { first: 'Nick' },
|
150
|
-
demo: { dob: '1921-09-03' },
|
151
|
-
contact: { phone: '444-444-4444' }
|
152
|
-
},
|
153
|
-
{
|
154
|
-
id: 3,
|
155
|
-
name: { first: 'Sam' },
|
156
|
-
demo: { dob: '1932-12-12' },
|
157
|
-
contact: { phone: '333-333-3333' }
|
158
|
-
}
|
159
|
-
]
|
160
|
-
end
|
161
|
-
|
162
|
-
specify 'works as advertised' do
|
163
|
-
expect(Bumblebee.parse_csv(columns, data)).to eq output
|
164
|
-
end
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
@@ -1,213 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
#
|
4
|
-
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
-
#
|
6
|
-
# This source code is licensed under the MIT license found in the
|
7
|
-
# LICENSE file in the root directory of this source tree.
|
8
|
-
#
|
9
|
-
|
10
|
-
require 'spec_helper'
|
11
|
-
|
12
|
-
describe ::Bumblebee::Column do
|
13
|
-
let(:object) do
|
14
|
-
OpenStruct.new(
|
15
|
-
name: 'Mattycakes',
|
16
|
-
dob: '1921-01-02',
|
17
|
-
pizza: 'Pepperoni',
|
18
|
-
license: OpenStruct.new(id: '123456')
|
19
|
-
)
|
20
|
-
end
|
21
|
-
|
22
|
-
let(:hash) do
|
23
|
-
{
|
24
|
-
name: 'Mattycakes',
|
25
|
-
dob: '1921-01-02',
|
26
|
-
pizza: 'Pepperoni',
|
27
|
-
license: { id: '123456' }
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
describe 'initialization' do
|
32
|
-
it 'should error if field is nil' do
|
33
|
-
expect { ::Bumblebee::Column.new(field: nil) }.to raise_error(ArgumentError)
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'should initialize with just a field' do
|
37
|
-
field = :name
|
38
|
-
|
39
|
-
column = ::Bumblebee::Column.new(field: field)
|
40
|
-
|
41
|
-
expect(column.field).to eq(field)
|
42
|
-
expect(column.header).to eq(field.to_s)
|
43
|
-
expect(column.to_csv).to eq([field])
|
44
|
-
expect(column.to_object).to eq([field.to_s])
|
45
|
-
end
|
46
|
-
|
47
|
-
describe 'header computation' do
|
48
|
-
it 'should compute from single field' do
|
49
|
-
field = :name
|
50
|
-
|
51
|
-
column = ::Bumblebee::Column.new(field: field)
|
52
|
-
|
53
|
-
expect(column.header).to eq(field.to_s)
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'should compute from multiple fields' do
|
57
|
-
field = [:name, 'is', :too, 22.4]
|
58
|
-
|
59
|
-
column = ::Bumblebee::Column.new(field: field)
|
60
|
-
|
61
|
-
expect(column.header).to eq(field.map(&:to_s).join('_'))
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should compute from a lambda literal' do
|
65
|
-
column = ::Bumblebee::Column.new(field: ->(o) {})
|
66
|
-
expect(column.header).to eq('proc')
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'should compute from a proc' do
|
70
|
-
column = ::Bumblebee::Column.new(field: proc {})
|
71
|
-
expect(column.header).to eq('proc')
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
describe '#csv_to_object' do
|
77
|
-
it 'should correctly extract the value using field' do
|
78
|
-
record = {
|
79
|
-
'name' => 'Nathan'
|
80
|
-
}
|
81
|
-
|
82
|
-
column = ::Bumblebee::Column.new(field: 'name')
|
83
|
-
|
84
|
-
expect(column.csv_to_object(record)).to eq(record)
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'should correctly extract the value using header' do
|
88
|
-
csv_row = {
|
89
|
-
'First Name' => 'Nathan'
|
90
|
-
}
|
91
|
-
|
92
|
-
record = {
|
93
|
-
'name' => 'Nathan'
|
94
|
-
}
|
95
|
-
|
96
|
-
column = ::Bumblebee::Column.new(field: 'name', header: 'First Name')
|
97
|
-
|
98
|
-
expect(column.csv_to_object(csv_row)).to eq(record)
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'should correctly extract the value using custom to_object value' do
|
102
|
-
csv_row = {
|
103
|
-
'First' => 'Nathan'
|
104
|
-
}
|
105
|
-
|
106
|
-
record = {
|
107
|
-
'name' => 'Nathan'
|
108
|
-
}
|
109
|
-
|
110
|
-
column = ::Bumblebee::Column.new(
|
111
|
-
field: 'name',
|
112
|
-
header: 'First Name',
|
113
|
-
to_object: 'First'
|
114
|
-
)
|
115
|
-
|
116
|
-
expect(column.csv_to_object(csv_row)).to eq(record)
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'should correctly extract the value using to_object with a proc' do
|
120
|
-
record = {
|
121
|
-
'name' => 'Nathan'
|
122
|
-
}
|
123
|
-
|
124
|
-
column = ::Bumblebee::Column.new(field: 'name', to_object: ->(o) { o['name'] })
|
125
|
-
|
126
|
-
expect(column.csv_to_object(record)).to eq(record)
|
127
|
-
end
|
128
|
-
|
129
|
-
it 'should correctly build up a nested hash' do
|
130
|
-
record = {
|
131
|
-
'name' => 'Nathan'
|
132
|
-
}
|
133
|
-
|
134
|
-
column = ::Bumblebee::Column.new(
|
135
|
-
field: :person,
|
136
|
-
to_object: [
|
137
|
-
'name',
|
138
|
-
->(o) { { first: o } }
|
139
|
-
]
|
140
|
-
)
|
141
|
-
|
142
|
-
expect(column.csv_to_object(record)).to eq(person: { first: record['name'] })
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
describe '#object_to_csv' do
|
147
|
-
context 'using field' do
|
148
|
-
context 'for single values' do
|
149
|
-
it 'should get csv value correctly' do
|
150
|
-
column = ::Bumblebee::Column.new(field: :name)
|
151
|
-
|
152
|
-
expect(column.object_to_csv(object)).to eq(object.name)
|
153
|
-
expect(column.object_to_csv(hash)).to eq(hash[:name])
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should return nil when does not exist' do
|
157
|
-
column = ::Bumblebee::Column.new(field: :doesnt_exist)
|
158
|
-
|
159
|
-
expect(column.object_to_csv(object)).to eq(nil)
|
160
|
-
expect(column.object_to_csv(hash)).to eq(nil)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context 'for arrays' do
|
165
|
-
it 'should get csv value correctly' do
|
166
|
-
column = ::Bumblebee::Column.new(field: %i[license id])
|
167
|
-
|
168
|
-
expect(column.object_to_csv(object)).to eq(object.license.id)
|
169
|
-
expect(column.object_to_csv(hash)).to eq(hash[:license][:id])
|
170
|
-
end
|
171
|
-
|
172
|
-
it 'should return nil when it hits dead end at beginning' do
|
173
|
-
column = ::Bumblebee::Column.new(field: %i[something that does not exist])
|
174
|
-
|
175
|
-
expect(column.object_to_csv(object)).to eq(nil)
|
176
|
-
expect(column.object_to_csv(hash)).to eq(nil)
|
177
|
-
end
|
178
|
-
|
179
|
-
it 'should return nil when it hits dead end in middle' do
|
180
|
-
column = ::Bumblebee::Column.new(field: %i[license doesnt_exist here])
|
181
|
-
|
182
|
-
expect(column.object_to_csv(object)).to eq(nil)
|
183
|
-
expect(column.object_to_csv(hash)).to eq(nil)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
context 'when mixing in procs' do
|
188
|
-
it 'should get csv value correctly when proc runs against end value' do
|
189
|
-
column = ::Bumblebee::Column.new(field: [:license, :id, ->(o) { "# #{o}" }])
|
190
|
-
|
191
|
-
expect(column.object_to_csv(object)).to eq("# #{object.license.id}")
|
192
|
-
expect(column.object_to_csv(hash)).to eq("# #{hash[:license][:id]}")
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'should get csv value correctly when proc runs against object-based value' do
|
196
|
-
column = ::Bumblebee::Column.new(field: [:license, ->(o) { "# #{o.id}" }])
|
197
|
-
expect(column.object_to_csv(object)).to eq("# #{object.license.id}")
|
198
|
-
|
199
|
-
column = ::Bumblebee::Column.new(field: [:license, ->(o) { "# #{o[:id]}" }])
|
200
|
-
expect(column.object_to_csv(hash)).to eq("# #{hash[:license][:id]}")
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'should not hit proc if ran against nil' do
|
204
|
-
column = ::Bumblebee::Column.new(field: [:doesnt_exist, ->(o) { "# #{o.id}" }])
|
205
|
-
expect(column.object_to_csv(object)).to eq(nil)
|
206
|
-
|
207
|
-
column = ::Bumblebee::Column.new(field: [:doesnt_exist, ->(o) { "# #{o[:id]}" }])
|
208
|
-
expect(column.object_to_csv(hash)).to eq(nil)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
end
|