drudgery 0.0.1
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.
- data/LICENSE +22 -0
- data/README.md +306 -0
- data/lib/drudgery/extractors/active_record_extractor.rb +15 -0
- data/lib/drudgery/extractors/csv_extractor.rb +19 -0
- data/lib/drudgery/extractors/sqlite3_extractor.rb +68 -0
- data/lib/drudgery/job.rb +54 -0
- data/lib/drudgery/loaders/active_record_import_loader.rb +16 -0
- data/lib/drudgery/loaders/active_record_loader.rb +15 -0
- data/lib/drudgery/loaders/csv_loader.rb +29 -0
- data/lib/drudgery/loaders/sqlite3_loader.rb +25 -0
- data/lib/drudgery/manager.rb +17 -0
- data/lib/drudgery/transformer.rb +30 -0
- data/lib/drudgery/version.rb +3 -0
- data/lib/drudgery.rb +45 -0
- data/spec/drudgery/extractors/active_record_extractor_spec.rb +79 -0
- data/spec/drudgery/extractors/csv_extractor_spec.rb +83 -0
- data/spec/drudgery/extractors/sqlite3_extractor_spec.rb +161 -0
- data/spec/drudgery/job_spec.rb +144 -0
- data/spec/drudgery/loaders/active_record_import_loader_spec.rb +57 -0
- data/spec/drudgery/loaders/active_record_loader_spec.rb +63 -0
- data/spec/drudgery/loaders/csv_loader_spec.rb +72 -0
- data/spec/drudgery/loaders/sqlite3_loader_spec.rb +57 -0
- data/spec/drudgery/manager_spec.rb +39 -0
- data/spec/drudgery/transformer_spec.rb +61 -0
- data/spec/drudgery_spec.rb +46 -0
- data/spec/spec_helper.rb +12 -0
- metadata +171 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
describe Drudgery::Extractors::ActiveRecordExtractor do
|
5
|
+
class Record < ActiveRecord::Base; end
|
6
|
+
|
7
|
+
describe '#initialize' do
|
8
|
+
it 'sets model to provided argument' do
|
9
|
+
model = mock
|
10
|
+
|
11
|
+
extractor = Drudgery::Extractors::ActiveRecordExtractor.new(model)
|
12
|
+
extractor.instance_variable_get('@model').must_equal model
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#extract' do
|
17
|
+
it 'finds records using model' do
|
18
|
+
model = mock
|
19
|
+
model.expects(:find_each)
|
20
|
+
|
21
|
+
extractor = Drudgery::Extractors::ActiveRecordExtractor.new(model)
|
22
|
+
extractor.extract
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'yields each record as a hash' do
|
26
|
+
record1 = mock
|
27
|
+
record1.expects(:attributes).returns({ :a => 1 })
|
28
|
+
|
29
|
+
record2 = mock
|
30
|
+
record2.expects(:attributes).returns({ :b => 2 })
|
31
|
+
|
32
|
+
model = mock
|
33
|
+
model.stubs(:find_each).multiple_yields([record1], [record2])
|
34
|
+
|
35
|
+
extractor = Drudgery::Extractors::ActiveRecordExtractor.new(model)
|
36
|
+
|
37
|
+
records = []
|
38
|
+
extractor.extract do |record|
|
39
|
+
records << record
|
40
|
+
end
|
41
|
+
|
42
|
+
records[0].must_equal({ :a => 1 })
|
43
|
+
records[1].must_equal({ :b => 2 })
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'without stubs' do
|
47
|
+
before(:each) do
|
48
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
49
|
+
ActiveRecord::Base.connection.create_table(:records) do |t|
|
50
|
+
t.integer :a
|
51
|
+
t.integer :b
|
52
|
+
end
|
53
|
+
|
54
|
+
Record.create!({ :a => 1, :b => 2 })
|
55
|
+
Record.create!({ :a => 3, :b => 4 })
|
56
|
+
Record.create!({ :a => 5, :b => 6 })
|
57
|
+
end
|
58
|
+
|
59
|
+
after(:each) do
|
60
|
+
ActiveRecord::Base.clear_active_connections!
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'yields each record as a hash' do
|
64
|
+
extractor = Drudgery::Extractors::ActiveRecordExtractor.new(Record)
|
65
|
+
|
66
|
+
records = []
|
67
|
+
extractor.extract do |record|
|
68
|
+
records << record
|
69
|
+
end
|
70
|
+
|
71
|
+
records.must_equal([
|
72
|
+
{ 'id' => 1, 'a' => 1, 'b' => 2 },
|
73
|
+
{ 'id' => 2, 'a' => 3, 'b' => 4 },
|
74
|
+
{ 'id' => 3, 'a' => 5, 'b' => 6 }
|
75
|
+
])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Drudgery::Extractors::CSVExtractor do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'sets filepath to provided filepath' do
|
6
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv')
|
7
|
+
extractor.instance_variable_get('@filepath').must_equal 'file.csv'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'initializes options hash' do
|
11
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv')
|
12
|
+
extractor.instance_variable_get('@options').must_equal({ :headers => true })
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'merges provided options with default options' do
|
16
|
+
options = { :col_sep => '|', :headers => %w[id name email] }
|
17
|
+
|
18
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv', options)
|
19
|
+
extractor.instance_variable_get('@options').must_equal({ :col_sep => '|', :headers => %w[id name email] })
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#extract' do
|
24
|
+
it 'parses records from file' do
|
25
|
+
CSV.expects(:foreach).with('file.csv', :headers => true)
|
26
|
+
|
27
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv')
|
28
|
+
extractor.extract
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'yields each record as a hash' do
|
32
|
+
record1 = mock
|
33
|
+
record1.expects(:to_hash).returns({ :a => 1 })
|
34
|
+
|
35
|
+
record2 = mock
|
36
|
+
record2.expects(:to_hash).returns({ :b => 2 })
|
37
|
+
|
38
|
+
CSV.stubs(:foreach).multiple_yields([record1], [record2])
|
39
|
+
|
40
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv')
|
41
|
+
|
42
|
+
records = []
|
43
|
+
extractor.extract do |record|
|
44
|
+
records << record
|
45
|
+
end
|
46
|
+
|
47
|
+
records[0].must_equal({ :a => 1 })
|
48
|
+
records[1].must_equal({ :b => 2 })
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'without stubs' do
|
52
|
+
before(:each) do
|
53
|
+
File.delete('file.csv') if File.exists?('file.csv')
|
54
|
+
end
|
55
|
+
|
56
|
+
after(:each) do
|
57
|
+
File.delete('file.csv') if File.exists?('file.csv')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'writes hash keys as header and records as rows' do
|
61
|
+
File.open('file.csv', 'w') do |f|
|
62
|
+
f.puts 'a,b'
|
63
|
+
f.puts '1,2'
|
64
|
+
f.puts '3,4'
|
65
|
+
f.puts '5,6'
|
66
|
+
end
|
67
|
+
|
68
|
+
extractor = Drudgery::Extractors::CSVExtractor.new('file.csv')
|
69
|
+
|
70
|
+
records = []
|
71
|
+
extractor.extract do |record|
|
72
|
+
records << record
|
73
|
+
end
|
74
|
+
|
75
|
+
records.must_equal([
|
76
|
+
{ 'a' => '1', 'b' => '2' },
|
77
|
+
{ 'a' => '3', 'b' => '4' },
|
78
|
+
{ 'a' => '5', 'b' => '6' }
|
79
|
+
])
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'sqlite3'
|
3
|
+
|
4
|
+
describe Drudgery::Extractors::SQLite3Extractor do
|
5
|
+
describe '#initialize' do
|
6
|
+
it 'sets db and table to provided arguments' do
|
7
|
+
db = mock
|
8
|
+
db.expects(:results_as_hash=).with(true)
|
9
|
+
db.expects(:type_translation=).with(true)
|
10
|
+
|
11
|
+
extractor = Drudgery::Extractors::SQLite3Extractor.new(db, 'tablename')
|
12
|
+
extractor.instance_variable_get('@db').must_equal db
|
13
|
+
extractor.instance_variable_get('@table').must_equal 'tablename'
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'initializes clauses hash' do
|
17
|
+
db = mock
|
18
|
+
db.stubs(:results_as_hash=)
|
19
|
+
db.stubs(:type_translation=)
|
20
|
+
|
21
|
+
extractor = Drudgery::Extractors::SQLite3Extractor.new(db, 'tablename')
|
22
|
+
extractor.instance_variable_get('@clauses').must_equal({})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'query building' do
|
27
|
+
before(:each) do
|
28
|
+
db = mock
|
29
|
+
db.stubs(:results_as_hash=)
|
30
|
+
db.stubs(:type_translation=)
|
31
|
+
|
32
|
+
@extractor = Drudgery::Extractors::SQLite3Extractor.new(db, 'tablename')
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#select' do
|
36
|
+
it 'sets select clause with provided expressions' do
|
37
|
+
@extractor.select('id', "(first_name || ' ' || last_name) AS name", 'email')
|
38
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :select => "id, (first_name || ' ' || last_name) AS name, email" })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#from' do
|
43
|
+
it 'sets from clause with provided expression' do
|
44
|
+
@extractor.from('table AS t')
|
45
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :from => 'table AS t' })
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#joins' do
|
50
|
+
it 'sets join clauses with provided clauses' do
|
51
|
+
joins = [
|
52
|
+
'JOIN table2 t2 ON t2.my_id = t1.id',
|
53
|
+
'LEFT OUTER JOIN table3 t3 ON t3.my_id = t2.id'
|
54
|
+
]
|
55
|
+
|
56
|
+
@extractor.joins(joins[0], joins[1])
|
57
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :joins => joins })
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '#group' do
|
62
|
+
it 'sets group clause with provided expressions' do
|
63
|
+
@extractor.group('id', 'email')
|
64
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :group => 'id, email' })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#where' do
|
69
|
+
it 'sets where clause with provided condition' do
|
70
|
+
@extractor.where('age >= 18 AND age < 50')
|
71
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :where => 'age >= 18 AND age < 50' })
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#having' do
|
76
|
+
it 'sets having clause with provided condition' do
|
77
|
+
@extractor.having('count(*) > 1')
|
78
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :having => 'count(*) > 1' })
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#order' do
|
83
|
+
it 'sets order clause with provided expressions' do
|
84
|
+
@extractor.order('id', 'email DESC')
|
85
|
+
@extractor.instance_variable_get('@clauses').must_equal({ :order => 'id, email DESC' })
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#extract' do
|
91
|
+
it 'selects records from db using defined query' do
|
92
|
+
db = mock
|
93
|
+
db.stubs(:results_as_hash=)
|
94
|
+
db.stubs(:type_translation=)
|
95
|
+
db.expects(:execute).with('SELECT * FROM tablename')
|
96
|
+
db.expects(:execute).with('SELECT age, count(*) AS nr_ages FROM tablename t table2 t2 ON t2.my_id = t.id WHERE age > 10 GROUP BY age HAVING count(*) > 1 ORDER BY nr_ages')
|
97
|
+
|
98
|
+
extractor = Drudgery::Extractors::SQLite3Extractor.new(db, 'tablename')
|
99
|
+
extractor.extract
|
100
|
+
|
101
|
+
extractor.select('age', 'count(*) AS nr_ages')
|
102
|
+
extractor.from('tablename t')
|
103
|
+
extractor.joins('table2 t2 ON t2.my_id = t.id')
|
104
|
+
extractor.where('age > 10')
|
105
|
+
extractor.group('age')
|
106
|
+
extractor.having('count(*) > 1')
|
107
|
+
extractor.order('nr_ages')
|
108
|
+
|
109
|
+
extractor.extract
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'yields each record as a hash' do
|
113
|
+
record1 = { :a => 1 }
|
114
|
+
record2 = { :b => 2 }
|
115
|
+
|
116
|
+
db = mock
|
117
|
+
db.stubs(:results_as_hash=)
|
118
|
+
db.stubs(:type_translation=)
|
119
|
+
db.stubs(:execute).multiple_yields([record1], [record2])
|
120
|
+
|
121
|
+
extractor = Drudgery::Extractors::SQLite3Extractor.new(db, 'tablename')
|
122
|
+
|
123
|
+
records = []
|
124
|
+
extractor.extract do |record|
|
125
|
+
records << record
|
126
|
+
end
|
127
|
+
|
128
|
+
records[0].must_equal({ :a => 1 })
|
129
|
+
records[1].must_equal({ :b => 2 })
|
130
|
+
end
|
131
|
+
|
132
|
+
describe 'without stubs' do
|
133
|
+
before(:each) do
|
134
|
+
@db = SQLite3::Database.new(':memory:')
|
135
|
+
@db.execute('CREATE TABLE records (a INTEGER, b INTEGER)')
|
136
|
+
@db.execute('INSERT INTO records (a, b) VALUES (1, 2)');
|
137
|
+
@db.execute('INSERT INTO records (a, b) VALUES (3, 4)');
|
138
|
+
@db.execute('INSERT INTO records (a, b) VALUES (5, 6)');
|
139
|
+
end
|
140
|
+
|
141
|
+
after(:each) do
|
142
|
+
@db.close
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'yields each record as a hash' do
|
146
|
+
extractor = Drudgery::Extractors::SQLite3Extractor.new(@db, 'records')
|
147
|
+
|
148
|
+
records = []
|
149
|
+
extractor.extract do |record|
|
150
|
+
records << record
|
151
|
+
end
|
152
|
+
|
153
|
+
records.must_equal([
|
154
|
+
{ 'a' => 1, 'b' => 2 },
|
155
|
+
{ 'a' => 3, 'b' => 4 },
|
156
|
+
{ 'a' => 5, 'b' => 6 }
|
157
|
+
])
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Drudgery::Job do
|
4
|
+
describe '#initialize' do
|
5
|
+
before(:each) do
|
6
|
+
@extractor = mock
|
7
|
+
@transformer = mock
|
8
|
+
@loader = mock
|
9
|
+
|
10
|
+
@job = Drudgery::Job.new(:extractor => @extractor, :transformer => @transformer, :loader => @loader)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'sets extractor, transformer, and loader with provided arguments' do
|
14
|
+
@job.instance_variable_get('@extractor').must_equal @extractor
|
15
|
+
@job.instance_variable_get('@transformer').must_equal @transformer
|
16
|
+
@job.instance_variable_get('@loader').must_equal @loader
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'initializes extractor, transformer, and loader if none provided' do
|
20
|
+
job = Drudgery::Job.new
|
21
|
+
job.instance_variable_get('@extractor').must_be_nil
|
22
|
+
job.instance_variable_get('@transformer').must_be_instance_of(Drudgery::Transformer)
|
23
|
+
job.instance_variable_get('@loader').must_be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'initializes records as array' do
|
27
|
+
@job.instance_variable_get('@records').must_equal []
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'initializes batch_size as 1000' do
|
31
|
+
@job.instance_variable_get('@batch_size').must_equal 1000
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#batch_size' do
|
36
|
+
it 'sets batch_size to provided value' do
|
37
|
+
job = Drudgery::Job.new
|
38
|
+
job.batch_size 2
|
39
|
+
job.instance_variable_get('@batch_size').must_equal 2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#extract' do
|
44
|
+
it 'instantiates extractor with type and args' do
|
45
|
+
Drudgery::Extractors.expects(:instantiate).with(:csv, 'filename.csv', :col_sep => '|')
|
46
|
+
|
47
|
+
job = Drudgery::Job.new
|
48
|
+
job.extract(:csv, 'filename.csv', :col_sep => '|')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'sets extractor' do
|
52
|
+
extractor = mock
|
53
|
+
|
54
|
+
Drudgery::Extractors.stubs(:instantiate).returns(extractor)
|
55
|
+
|
56
|
+
job = Drudgery::Job.new
|
57
|
+
job.extract(:csv, 'filename.csv', :col_sep => '|')
|
58
|
+
|
59
|
+
job.instance_variable_get('@extractor').must_equal extractor
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#transform' do
|
64
|
+
it 'registers provided proc with transformer' do
|
65
|
+
block = Proc.new { |data, cache| data }
|
66
|
+
|
67
|
+
transformer = mock
|
68
|
+
transformer.expects(:register).with(block)
|
69
|
+
|
70
|
+
job = Drudgery::Job.new(:transformer => transformer)
|
71
|
+
job.transform(&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'registers provided block with transformer' do
|
75
|
+
transformer = mock
|
76
|
+
transformer.expects(:register).with { |data, cache| data }
|
77
|
+
|
78
|
+
job = Drudgery::Job.new(:transformer => transformer)
|
79
|
+
job.transform { |data, cache| data }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#load' do
|
84
|
+
it 'instantiates loader with type with args' do
|
85
|
+
Drudgery::Loaders.expects(:instantiate).with(:sqlite3, 'db.sqlite3', 'tablename')
|
86
|
+
|
87
|
+
job = Drudgery::Job.new
|
88
|
+
job.load(:sqlite3, 'db.sqlite3', 'tablename')
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'sets extractor' do
|
92
|
+
loader = mock
|
93
|
+
|
94
|
+
Drudgery::Loaders.expects(:instantiate).with(:sqlite3, 'db.sqlite3', 'tablename').returns(loader)
|
95
|
+
|
96
|
+
job = Drudgery::Job.new
|
97
|
+
job.load(:sqlite3, 'db.sqlite3', 'tablename')
|
98
|
+
job.instance_variable_get('@loader').must_equal loader
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#perform' do
|
103
|
+
it 'extracts records from extractor' do
|
104
|
+
extractor = mock
|
105
|
+
extractor.expects(:extract).yields({ 'a' => 1 })
|
106
|
+
|
107
|
+
loader = mock
|
108
|
+
loader.stubs(:load)
|
109
|
+
|
110
|
+
job = Drudgery::Job.new(:extractor => extractor, :loader => loader)
|
111
|
+
|
112
|
+
job.perform
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'transforms records with transformer' do
|
116
|
+
extractor = mock
|
117
|
+
extractor.stubs(:extract).yields({ 'a' => 1 })
|
118
|
+
|
119
|
+
transformer = mock
|
120
|
+
transformer.expects(:transform).with({ 'a' => 1 }).returns({ :a => 1 })
|
121
|
+
|
122
|
+
loader = mock
|
123
|
+
loader.stubs(:load)
|
124
|
+
|
125
|
+
job = Drudgery::Job.new(:extractor => extractor, :transformer => transformer, :loader => loader)
|
126
|
+
|
127
|
+
job.perform
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'loads records with loader in batches' do
|
131
|
+
extractor = mock
|
132
|
+
extractor.stubs(:extract).multiple_yields([{ 'a' => 1 }], [{ 'b' => 2 }], [{ 'c' => 3 }])
|
133
|
+
|
134
|
+
loader = mock
|
135
|
+
loader.expects(:load).with([{ :a => 1 }, { :b => 2 }])
|
136
|
+
loader.expects(:load).with([{ :c => 3 }])
|
137
|
+
|
138
|
+
job = Drudgery::Job.new(:extractor => extractor, :loader => loader)
|
139
|
+
job.batch_size 2
|
140
|
+
|
141
|
+
job.perform
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
require 'activerecord-import'
|
4
|
+
|
5
|
+
describe Drudgery::Loaders::ActiveRecordImportLoader do
|
6
|
+
class Record < ActiveRecord::Base; end
|
7
|
+
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'sets model to provided argument' do
|
10
|
+
model = mock
|
11
|
+
|
12
|
+
loader = Drudgery::Loaders::ActiveRecordImportLoader.new(model)
|
13
|
+
loader.instance_variable_get('@model').must_equal model
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#load' do
|
18
|
+
it 'write records using model.import' do
|
19
|
+
record1 = { :a => 1, :b => 2 }
|
20
|
+
record2 = { :a => 3, :b => 4 }
|
21
|
+
|
22
|
+
model = mock
|
23
|
+
model.expects(:import).with([:a, :b], [[1, 2], [3, 4]], :validate => false)
|
24
|
+
|
25
|
+
loader = Drudgery::Loaders::ActiveRecordImportLoader.new(model)
|
26
|
+
loader.load([record1, record2])
|
27
|
+
end
|
28
|
+
|
29
|
+
describe 'without stubs' do
|
30
|
+
before(:each) do
|
31
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
32
|
+
ActiveRecord::Base.connection.create_table(:records) do |t|
|
33
|
+
t.integer :a
|
34
|
+
t.integer :b
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
after(:each) do
|
39
|
+
ActiveRecord::Base.clear_active_connections!
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'yields each record as a hash' do
|
43
|
+
record1 = { :a => 1, :b => 2 }
|
44
|
+
record2 = { :a => 3, :b => 4 }
|
45
|
+
|
46
|
+
loader = Drudgery::Loaders::ActiveRecordImportLoader.new(Record)
|
47
|
+
loader.load([record1, record2])
|
48
|
+
|
49
|
+
records = Record.all.map(&:attributes)
|
50
|
+
records.must_equal([
|
51
|
+
{ 'id' => 1, 'a' => 1, 'b' => 2 },
|
52
|
+
{ 'id' => 2, 'a' => 3, 'b' => 4 }
|
53
|
+
])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
describe Drudgery::Loaders::ActiveRecordLoader do
|
5
|
+
class Record < ActiveRecord::Base; end
|
6
|
+
|
7
|
+
describe '#initialize' do
|
8
|
+
it 'sets model to provided argument' do
|
9
|
+
model = mock
|
10
|
+
|
11
|
+
loader = Drudgery::Loaders::ActiveRecordLoader.new(model)
|
12
|
+
loader.instance_variable_get('@model').must_equal model
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#load' do
|
17
|
+
it 'write records using model.create' do
|
18
|
+
record1 = { :a => 1 }
|
19
|
+
record2 = { :a => 2 }
|
20
|
+
|
21
|
+
obj1 = mock
|
22
|
+
obj2 = mock
|
23
|
+
|
24
|
+
model = mock
|
25
|
+
model.expects(:new).with(record1).returns(obj1)
|
26
|
+
model.expects(:new).with(record2).returns(obj2)
|
27
|
+
|
28
|
+
obj1.expects(:save).with(:validate => false)
|
29
|
+
obj2.expects(:save).with(:validate => false)
|
30
|
+
|
31
|
+
loader = Drudgery::Loaders::ActiveRecordLoader.new(model)
|
32
|
+
loader.load([record1, record2])
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'without stubs' do
|
36
|
+
before(:each) do
|
37
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
38
|
+
ActiveRecord::Base.connection.create_table(:records) do |t|
|
39
|
+
t.integer :a
|
40
|
+
t.integer :b
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
after(:each) do
|
45
|
+
ActiveRecord::Base.clear_active_connections!
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'yields each record as a hash' do
|
49
|
+
record1 = { :a => 1, :b => 2 }
|
50
|
+
record2 = { :a => 3, :b => 4 }
|
51
|
+
|
52
|
+
loader = Drudgery::Loaders::ActiveRecordLoader.new(Record)
|
53
|
+
loader.load([record1, record2])
|
54
|
+
|
55
|
+
records = Record.all.map(&:attributes)
|
56
|
+
records.must_equal([
|
57
|
+
{ 'id' => 1, 'a' => 1, 'b' => 2 },
|
58
|
+
{ 'id' => 2, 'a' => 3, 'b' => 4 }
|
59
|
+
])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Drudgery::Loaders::CSVLoader do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'sets filepath to provided filepath' do
|
6
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv')
|
7
|
+
loader.instance_variable_get('@filepath').must_equal 'file.csv'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'initializes write_headers boolean' do
|
11
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv')
|
12
|
+
loader.instance_variable_get('@write_headers').must_equal true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'sets options to provided options' do
|
16
|
+
options = { :col_sep => '|' }
|
17
|
+
|
18
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv', options)
|
19
|
+
loader.instance_variable_get('@options').must_equal({ :col_sep => '|' })
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#load' do
|
24
|
+
it 'opens CSV file to append records' do
|
25
|
+
CSV.expects(:open).with('file.csv', 'a', :col_sep => '|')
|
26
|
+
|
27
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv', :col_sep => '|')
|
28
|
+
loader.load([{}])
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'writes hash keys as header and records as rows' do
|
32
|
+
record1 = { :a => 1, :b => 2 }
|
33
|
+
record2 = { :a => 3, :b => 4 }
|
34
|
+
record3 = { :a => 5, :b => 6 }
|
35
|
+
|
36
|
+
csv = mock
|
37
|
+
csv.expects(:<<).with([:a, :b])
|
38
|
+
csv.expects(:<<).with([1, 2])
|
39
|
+
csv.expects(:<<).with([3, 4])
|
40
|
+
csv.expects(:<<).with([5, 6])
|
41
|
+
|
42
|
+
CSV.expects(:open).with('file.csv', 'a', {}).yields(csv).times(2)
|
43
|
+
|
44
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv')
|
45
|
+
loader.load([record1, record2])
|
46
|
+
loader.load([record3])
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'without stubs' do
|
50
|
+
before(:each) do
|
51
|
+
File.delete('file.csv') if File.exists?('file.csv')
|
52
|
+
end
|
53
|
+
|
54
|
+
after(:each) do
|
55
|
+
File.delete('file.csv') if File.exists?('file.csv')
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'writes hash keys as header and records as rows' do
|
59
|
+
record1 = { :a => 1, :b => 2 }
|
60
|
+
record2 = { :a => 3, :b => 4 }
|
61
|
+
record3 = { :a => 5, :b => 6 }
|
62
|
+
|
63
|
+
loader = Drudgery::Loaders::CSVLoader.new('file.csv')
|
64
|
+
loader.load([record1, record2])
|
65
|
+
loader.load([record3])
|
66
|
+
|
67
|
+
records = File.readlines('file.csv').map { |line| line.strip.split(',') }
|
68
|
+
records.must_equal [%w[a b], %w[1 2], %w[3 4], %w[5 6]]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|