forklift_etl 1.1.12 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 72c15001e2a6f2164be9fbe2ef78da4d5e131d6c
4
+ data.tar.gz: 5dfd8551cee1c2a19af8ffe49c9a73bb9b1b5bdf
5
+ SHA512:
6
+ metadata.gz: a0763e36c35340ee5e55e78fcef2aa54533d6e4aa18fa9ac16b64835b7fa58f32195482a78f76e4e8a2dc3e380e8513cdd48c364b9bd65b20180af1b55e2ca7c
7
+ data.tar.gz: ae1472bc5ce7a6ebf0be6b6e896bc22211818bc6db9e405d085c68ae570ecef2fa1eee757ff85163af9771b928cecd4aa69fce84a865c449ddfe28c35ce3b2df
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- forklift_etl (1.1.12)
4
+ forklift_etl (1.2.0)
5
5
  activesupport (~> 4.0, >= 4.0.0)
6
6
  elasticsearch (~> 1.0, >= 1.0.0)
7
7
  lumberjack (~> 1.0, >= 1.0.0)
@@ -18,7 +18,7 @@ GEM
18
18
  thread_safe (~> 0.3, >= 0.3.4)
19
19
  tzinfo (~> 1.1)
20
20
  addressable (2.3.6)
21
- awesome_print (1.6.0)
21
+ awesome_print (1.6.1)
22
22
  diff-lcs (1.2.5)
23
23
  elasticsearch (1.0.6)
24
24
  elasticsearch-api (= 1.0.6)
@@ -31,17 +31,17 @@ GEM
31
31
  email_spec (1.6.0)
32
32
  launchy (~> 2.1)
33
33
  mail (~> 2.2)
34
- faraday (0.9.0)
34
+ faraday (0.9.1)
35
35
  multipart-post (>= 1.2, < 3)
36
36
  i18n (0.7.0)
37
- json (1.8.1)
37
+ json (1.8.2)
38
38
  launchy (2.4.3)
39
39
  addressable (~> 2.3)
40
40
  lumberjack (1.0.9)
41
41
  mail (2.6.3)
42
42
  mime-types (>= 1.16, < 3)
43
43
  mime-types (2.4.3)
44
- minitest (5.5.0)
44
+ minitest (5.5.1)
45
45
  multi_json (1.10.1)
46
46
  multipart-post (2.0.0)
47
47
  mysql2 (0.3.17)
@@ -38,32 +38,32 @@ module Forklift
38
38
  raise 'not implemented'
39
39
  end
40
40
 
41
- def exec(path)
41
+ def exec(path, *args)
42
42
  begin
43
- exec!(path)
43
+ exec!(path, &args)
44
44
  rescue Exception => e
45
45
  forklift.logger.log(e)
46
46
  end
47
47
  end
48
48
 
49
- def exec!(path)
49
+ def exec!(path, *args)
50
50
  forklift.logger.log "Running script: #{path}"
51
51
  extension = path.split(".").last
52
52
  if(extension == "rb" || extension == "ruby")
53
- exec_ruby(path)
53
+ exec_ruby(path, *args)
54
54
  else
55
- exec_script(path)
55
+ exec_script(path, *args)
56
56
  end
57
57
  end
58
58
 
59
- def exec_ruby(path)
59
+ def exec_ruby(path, *args)
60
60
  klass = forklift.utils.class_name_from_file(path)
61
61
  require path
62
62
  model = eval("#{klass}.new")
63
- model.do!(self, forklift)
63
+ model.do!(self, forklift, *args)
64
64
  end
65
65
 
66
- def exec_script(path)
66
+ def exec_script(path, *args)
67
67
  raise 'not implemented'
68
68
  end
69
69
 
data/lib/forklift/plan.rb CHANGED
@@ -33,6 +33,7 @@ module Forklift
33
33
  begin
34
34
  loader = "Forklift::Connection::#{type.camelcase}.new(db_config, self)"
35
35
  connection = eval(loader)
36
+ connection.connect
36
37
  connections[type.to_sym][name.to_sym] = connection
37
38
  logger.debug "loaded a #{type.camelcase} connection from #{f}"
38
39
  rescue Exception => e
@@ -42,6 +43,13 @@ module Forklift
42
43
  end
43
44
  end
44
45
 
46
+ def disconnect!
47
+ connections.each do |k, collection|
48
+ collection.each do |k, connection|
49
+ connection.disconnect
50
+ end
51
+ end
52
+ end
45
53
 
46
54
  def default_error_handler
47
55
  return lambda {|name, e| raise e }
@@ -18,6 +18,9 @@ module Forklift
18
18
  @forklift
19
19
  end
20
20
 
21
+ def connect; end
22
+ def disconnect; end
23
+
21
24
  def read(size=forklift.config[:batch_size])
22
25
  data = []
23
26
  CSV.foreach(config[:file], headers: true, converters: :all) do |row|
@@ -7,7 +7,6 @@ module Forklift
7
7
  def initialize(config, forklift)
8
8
  @config = config
9
9
  @forklift = forklift
10
- @client = ::Elasticsearch::Client.new(config)
11
10
  end
12
11
 
13
12
  def config
@@ -18,6 +17,14 @@ module Forklift
18
17
  @forklift
19
18
  end
20
19
 
20
+ def connect
21
+ @client = ::Elasticsearch::Client.new(config)
22
+ end
23
+
24
+ def disconnect
25
+ @client = nil
26
+ end
27
+
21
28
  def read(index, query, looping=true, from=0, size=forklift.config[:batch_size])
22
29
  offset = 0
23
30
  loop_count = 0
@@ -8,8 +8,14 @@ module Forklift
8
8
  def initialize(config, forklift)
9
9
  @config = config
10
10
  @forklift = forklift
11
- @client = Mysql2::Client.new(config)
12
- # q("USE #{config['database']}")
11
+ end
12
+
13
+ def connect
14
+ @client = Mysql2::Client.new(@config)
15
+ end
16
+
17
+ def disconnect
18
+ @client.close
13
19
  end
14
20
 
15
21
  def config
@@ -1,3 +1,3 @@
1
1
  module Forklift
2
- VERSION = "1.1.12"
2
+ VERSION = "1.2.0"
3
3
  end
data/readme.md CHANGED
@@ -413,20 +413,31 @@ Forklift allows you to create both Ruby transformations and script transformatio
413
413
  - It is up to the transport to define `exec_script`, and not all transports will support it. Mysql can run `.sql` files, but there is not an equivalent for elasticsearch.
414
414
  - `.exec` runs and logs exceptions, while `.exec!` will raise on an error. For example, `destination.exec("./transformations/cleanup.rb")` will run cleanup.rb on the destination database.
415
415
  - Script files are run as-is, but ruby transformations must define a `do!` method in their class and are passed `def do!(connection, forklift)`
416
+ - args is optional, and can be passed in from your plan
416
417
 
417
418
  ```ruby
418
419
  # Example transformation to count users
419
420
  # count_users.rb
420
421
 
421
422
  class CountUsers
422
- def do!(connection, forklift)
423
+ def do!(connection, forklift, args)
423
424
  forklift.logger.log "counting users"
424
425
  count = connection.count('users')
425
- forklift.logger.log "found #{count} users"
426
+ forklift.logger.log "[#{args.name}] found #{count} users"
426
427
  end
427
428
  end
428
429
  ```
429
430
 
431
+ ```ruby
432
+ # in your plan.rb
433
+ plan = Forklift::Plan.new
434
+ plan.do! do
435
+ destination = plan.connections[:mysql][:destination]
436
+ destination.exec!("./transformations/combined_name.sql", {name: 'user counter'})
437
+
438
+ end
439
+ ```
440
+
430
441
  ## Options & Notes
431
442
  - Thanks to [@rahilsondhi](https://github.com/rahilsondhi) from [InternMatch](http://www.internmatch.com/) for all his help
432
443
  - email_options is a hash consumed by the [Pony mail gem](https://github.com/benprew/pony)
@@ -10,6 +10,7 @@ describe 'basics' do
10
10
  tables << row.values[0]
11
11
  end
12
12
  expect(tables.count).to eql 3
13
+ client.close
13
14
 
14
15
  client = SpecClient.mysql('forklift_test_source_b')
15
16
  tables = []
@@ -17,6 +18,7 @@ describe 'basics' do
17
18
  tables << row.values[0]
18
19
  end
19
20
  expect(tables.count).to eql 1
21
+ client.close
20
22
  end
21
23
 
22
24
  it 'seeded the elasticsearch db' do
@@ -17,6 +17,7 @@ describe 'elasticsearch' do
17
17
  @rows = (@rows + data)
18
18
  }
19
19
  }
20
+ plan.disconnect!
20
21
 
21
22
  expect(@rows.length).to eql 5
22
23
  end
@@ -32,6 +33,7 @@ describe 'elasticsearch' do
32
33
  @rows = (@rows + data)
33
34
  }
34
35
  }
36
+ plan.disconnect!
35
37
 
36
38
  expect(@rows.length).to eql 3
37
39
  end
@@ -46,6 +48,7 @@ describe 'elasticsearch' do
46
48
  destination = plan.connections[:elasticsearch][:forklift_test]
47
49
  destination.write(data, index)
48
50
  }
51
+ plan.disconnect!
49
52
 
50
53
  destination = SpecClient.elasticsearch('forklift_test')
51
54
  count = destination.count({ index: index })["count"]
@@ -63,6 +66,7 @@ describe 'elasticsearch' do
63
66
  destination = plan.connections[:elasticsearch][:forklift_test]
64
67
  destination.write(data, index, true)
65
68
  }
69
+ plan.disconnect!
66
70
 
67
71
  destination = SpecClient.elasticsearch('forklift_test')
68
72
  count = destination.count({ index: index })["count"]
@@ -91,5 +95,6 @@ describe 'elasticsearch' do
91
95
  destination.delete_index(index)
92
96
  expect { client.search({ index: index }) }.to raise_error(/IndexMissingException/)
93
97
  }
98
+ plan.disconnect!
94
99
  end
95
100
  end
@@ -18,6 +18,7 @@ describe 'multiple trasport types' do
18
18
  destination = plan.connections[:mysql][:forklift_test_destination]
19
19
  source.read(index, query) {|data| destination.write(data, table) }
20
20
  }
21
+ plan.disconnect!
21
22
 
22
23
  destination = SpecClient.mysql('forklift_test_destination')
23
24
  rows = destination.query("select count(1) as 'count' from es_import").first["count"]
@@ -34,6 +35,7 @@ describe 'multiple trasport types' do
34
35
  destination = plan.connections[:mysql][:forklift_test_destination]
35
36
  source.read(index, query, false, 0, 3) {|data| destination.write(data, table) }
36
37
  }
38
+ plan.disconnect!
37
39
 
38
40
  destination = SpecClient.mysql('forklift_test_destination')
39
41
  rows = destination.query("select count(1) as 'count' from es_import").first["count"]
@@ -61,6 +63,7 @@ describe 'multiple trasport types' do
61
63
  destination.write(clean_data, table)
62
64
  }
63
65
  }
66
+ plan.disconnect!
64
67
 
65
68
  destination = SpecClient.mysql('forklift_test_destination')
66
69
  max = destination.query("select max(viewed_at) as 'max' from es_import").first["max"]
@@ -85,6 +88,7 @@ describe 'multiple trasport types' do
85
88
  destination = plan.connections[:elasticsearch][:forklift_test]
86
89
  source.read("select * from #{table}") {|data| destination.write(data, index) }
87
90
  }
91
+ plan.disconnect!
88
92
 
89
93
  destination = SpecClient.elasticsearch('forklift_test')
90
94
  count = destination.count({ index: index })["count"]
@@ -102,6 +106,7 @@ describe 'multiple trasport types' do
102
106
  destination.write(data, index)
103
107
  }
104
108
  }
109
+ plan.disconnect!
105
110
 
106
111
  destination = SpecClient.elasticsearch('forklift_test')
107
112
  count = destination.count({ index: index })["count"]
@@ -21,6 +21,7 @@ describe 'mysql patterns' do
21
21
 
22
22
  expect(destination.tables.length).to eql 3
23
23
  }
24
+ plan.disconnect!
24
25
  end
25
26
 
26
27
  it "can do an incramental data pipe with only updated data" do
@@ -42,6 +43,7 @@ describe 'mysql patterns' do
42
43
  expect(destination.count('users')).to eql 5
43
44
  expect(destination.read('select first_name from users where id = 1')[0][:first_name]).to eql 'EvanAgain'
44
45
  }
46
+ plan.disconnect!
45
47
  end
46
48
 
47
49
  it "(optimistic_pipe) can determine if it should do an incramental or full pipe" do
@@ -52,6 +54,7 @@ describe 'mysql patterns' do
52
54
  expect(Forklift::Patterns::Mysql.can_incremental_pipe?(source, 'sales', source, 'sales')).to eql false
53
55
  expect(Forklift::Patterns::Mysql.can_incremental_pipe?(source, 'products', source, 'products')).to eql true
54
56
  }
57
+ plan.disconnect!
55
58
  end
56
59
 
57
60
  it "can run the mysql_optimistic_import pattern" do
@@ -72,6 +75,7 @@ describe 'mysql patterns' do
72
75
  expect(destination.count('users')).to eql 5
73
76
  expect(destination.read('select first_name from users where id = 1')[0][:first_name]).to eql 'EvanAgain'
74
77
  }
78
+ plan.disconnect!
75
79
  end
76
80
 
77
81
  it "can write the high_water_mark"
@@ -16,6 +16,7 @@ describe 'mysql' do
16
16
  @rows = (@rows + data)
17
17
  }
18
18
  }
19
+ plan.disconnect!
19
20
 
20
21
  expect(@rows.length).to eql 5
21
22
  end
@@ -30,6 +31,7 @@ describe 'mysql' do
30
31
  @rows = (@rows + data)
31
32
  }
32
33
  }
34
+ plan.disconnect!
33
35
 
34
36
  expect(@rows.length).to eql 3
35
37
  end
@@ -45,6 +47,7 @@ describe 'mysql' do
45
47
  destination = plan.connections[:mysql][:forklift_test_source_a]
46
48
  destination.write(data, table)
47
49
  }
50
+ plan.disconnect!
48
51
 
49
52
  destination = SpecClient.mysql('forklift_test_source_a')
50
53
  count = destination.query('select count(1) as "count" from users').first['count']
@@ -61,6 +64,7 @@ describe 'mysql' do
61
64
  destination = plan.connections[:mysql][:forklift_test_source_a]
62
65
  destination.write(data, table)
63
66
  }
67
+ plan.disconnect!
64
68
 
65
69
  destination = SpecClient.mysql('forklift_test_source_a')
66
70
  count = destination.query('select count(1) as "count" from users').first['count']
@@ -88,6 +92,7 @@ describe 'mysql' do
88
92
  destination = plan.connections[:mysql][:forklift_test_source_a]
89
93
  destination.write(data, table)
90
94
  }
95
+ plan.disconnect!
91
96
 
92
97
  destination = SpecClient.mysql('forklift_test_source_a')
93
98
  cols = []
@@ -117,6 +122,7 @@ describe 'mysql' do
117
122
  destination = plan.connections[:mysql][:forklift_test_source_a]
118
123
  destination.write(data, table)
119
124
  }
125
+ plan.disconnect!
120
126
 
121
127
  destination = SpecClient.mysql('forklift_test_source_a')
122
128
  cols = []
@@ -151,6 +157,7 @@ describe 'mysql' do
151
157
  destination = plan.connections[:mysql][:forklift_test_source_a]
152
158
  destination.write(data, table)
153
159
  }
160
+ plan.disconnect!
154
161
 
155
162
  count = raw.query("SHOW COLUMNS FROM #{table}").count
156
163
  expect(count).to eql 7
@@ -168,6 +175,7 @@ describe 'mysql' do
168
175
  destination = plan.connections[:mysql][:forklift_test_source_a]
169
176
  destination.write(data, table)
170
177
  }
178
+ plan.disconnect!
171
179
 
172
180
  destination = SpecClient.mysql('forklift_test_source_a')
173
181
  cols = []
@@ -200,6 +208,7 @@ describe 'mysql' do
200
208
  destination = plan.connections[:mysql][:forklift_test_source_a]
201
209
  destination.write(data, table)
202
210
  }
211
+ plan.disconnect!
203
212
 
204
213
  destination = SpecClient.mysql('forklift_test_source_a')
205
214
  cols = []
@@ -226,6 +235,7 @@ describe 'mysql' do
226
235
  destination = plan.connections[:mysql][:forklift_test_source_a]
227
236
  destination.write(data, table)
228
237
  }
238
+ plan.disconnect!
229
239
 
230
240
  destination = SpecClient.mysql('forklift_test_source_a')
231
241
  cols = []
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'transformations' do
4
+
5
+ before(:each) do
6
+ SpecSeeds.setup_mysql
7
+ end
8
+
9
+ it "can run a native transformation" do
10
+ plan = SpecPlan.new
11
+ @rows = []
12
+
13
+ raw = SpecClient.mysql('forklift_test_destination')
14
+
15
+ plan.do! {
16
+ source = plan.connections[:mysql][:forklift_test_source_a]
17
+ destination = plan.connections[:mysql][:forklift_test_destination]
18
+ source.read('select * from `users`') {|data| destination.write(data, 'users') }
19
+
20
+ expect( destination.columns("users").include?("full_name") ).to eql false
21
+
22
+ transformation_file = "#{File.dirname(__FILE__)}/../template/spec_user_transformation.sql"
23
+ destination.exec!(transformation_file)
24
+
25
+ expect( destination.columns("users").include?("full_name") ).to eql true
26
+ }
27
+ plan.disconnect!
28
+ end
29
+
30
+ it "can run a ruby transformation" do
31
+ plan = SpecPlan.new
32
+ @rows = []
33
+
34
+ raw = SpecClient.mysql('forklift_test_destination')
35
+
36
+ plan.do! {
37
+ source = plan.connections[:mysql][:forklift_test_source_a]
38
+ destination = plan.connections[:mysql][:forklift_test_destination]
39
+ source.read('select * from `users`') {|data| destination.write(data, 'users') }
40
+
41
+ expect( destination.columns("users").include?("full_name") ).to eql false
42
+
43
+ transformation_file = "#{File.dirname(__FILE__)}/../template/spec_user_transformation.rb"
44
+ destination.exec!(transformation_file, {prefix: 'my_prefix' })
45
+
46
+ expect( destination.columns("users").include?("full_name") ).to eql true
47
+
48
+ data = destination.read('select * from `users` where email="evan@example.com"')
49
+ expect( data.first[:full_name] ).to eql 'my_prefix Evan T'
50
+ }
51
+ plan.disconnect!
52
+ end
53
+
54
+ end
@@ -0,0 +1,8 @@
1
+ class SpecUserTransformation
2
+
3
+ def do!(connection, forklift, args)
4
+ connection.q("ALTER TABLE `users` ADD `full_name` VARCHAR(255) NULL DEFAULT NULL AFTER `updated_at`;")
5
+ connection.q("UPDATE `users` SET full_name = CONCAT('#{args[:prefix]}', ' ', first_name, ' ', last_name);")
6
+ end
7
+
8
+ end
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `users` ADD `full_name` VARCHAR(255) NULL DEFAULT NULL AFTER `updated_at`;
2
+ UPDATE `users` SET full_name = CONCAT(first_name, ' ', last_name);
@@ -16,6 +16,7 @@ describe Forklift::Connection::Mysql do
16
16
  expect(source.tables).to include 'products'
17
17
  expect(source.tables).to include 'sales'
18
18
  }
19
+ plan.disconnect!
19
20
  end
20
21
 
21
22
  it "can delte a table" do
@@ -27,6 +28,7 @@ describe Forklift::Connection::Mysql do
27
28
  source.drop! table
28
29
  expect(source.tables).to_not include 'users'
29
30
  }
31
+ plan.disconnect!
30
32
  end
31
33
 
32
34
  it "can count the rows in a table" do
@@ -36,6 +38,7 @@ describe Forklift::Connection::Mysql do
36
38
  source = plan.connections[:mysql][:forklift_test_source_a]
37
39
  expect(source.count(table)).to eql 5
38
40
  }
41
+ plan.disconnect!
39
42
  end
40
43
 
41
44
  it "can truncate a table (both with and without !)" do
@@ -48,6 +51,7 @@ describe Forklift::Connection::Mysql do
48
51
  expect(source.count(table)).to eql 0
49
52
  expect { source.truncate(table) }.to_not raise_error
50
53
  }
54
+ plan.disconnect!
51
55
  end
52
56
 
53
57
  it 'trunacte! will raise if the table does not exist' do
@@ -57,6 +61,7 @@ describe Forklift::Connection::Mysql do
57
61
  source = plan.connections[:mysql][:forklift_test_source_a]
58
62
  expect { source.truncate!(table) }.to raise_error(/Table 'forklift_test_source_a.other_table' doesn't exist/)
59
63
  }
64
+ plan.disconnect!
60
65
  end
61
66
 
62
67
  it "can get the columns of a table" do
@@ -69,6 +74,7 @@ describe Forklift::Connection::Mysql do
69
74
  expect(source.columns(table)).to include 'product_id'
70
75
  expect(source.columns(table)).to include 'timestamp'
71
76
  }
77
+ plan.disconnect!
72
78
  end
73
79
 
74
80
  it "can create a mysqldump" do
@@ -78,6 +84,7 @@ describe Forklift::Connection::Mysql do
78
84
  source = plan.connections[:mysql][:forklift_test_source_a]
79
85
  source.dump(dump)
80
86
  }
87
+ plan.disconnect!
81
88
 
82
89
  expect(File.exists?(dump)).to eql true
83
90
  contents = Zlib::GzipReader.new(StringIO.new(File.read(dump))).read
@@ -21,6 +21,7 @@ describe 'misc forklift core' do
21
21
  email_template = "#{File.dirname(__FILE__)}/../../template/spec_email_template.erb"
22
22
  @email = plan.mailer.send_template(email_args, email_template, email_variables).first
23
23
  }
24
+ plan.disconnect!
24
25
 
25
26
  expect(@email).to deliver_to("YOU@FAKE.com")
26
27
  expect(@email).to have_subject(/Forklift has moved your database/)
@@ -11,6 +11,7 @@ describe 'misc forklift core' do
11
11
  }
12
12
  }.to raise_error 'BREAK'
13
13
  plan.pid.delete!
14
+ plan.disconnect!
14
15
  end
15
16
 
16
17
  it 'can make error handlers' do
@@ -24,6 +25,7 @@ describe 'misc forklift core' do
24
25
  plan.do! {
25
26
  plan.step("step_a", error_handler){ raise 'BREAK' }
26
27
  }
28
+ plan.disconnect!
27
29
 
28
30
  expect(name).to eql :step_a
29
31
  expect(ex.to_s).to eql 'BREAK'
@@ -11,6 +11,7 @@ describe 'misc forklift core' do
11
11
  expect(File.exists?(pid)).to eql true
12
12
  expect(File.read(pid).to_i).to eql Process.pid
13
13
  }
14
+ plan.disconnect!
14
15
  expect(File.exists?(pid)).to eql false
15
16
  end
16
17
 
@@ -19,6 +20,7 @@ describe 'misc forklift core' do
19
20
  plan.pid.store!
20
21
  expect { plan.do! }.to raise_error SystemExit
21
22
  plan.pid.delete!
23
+ plan.disconnect!
22
24
  end
23
25
  end
24
26
 
@@ -20,6 +20,7 @@ describe 'misc forklift core' do
20
20
  plan.step("b"){ steps_run << 'b' }
21
21
  plan.step("c"){ steps_run << 'c' }
22
22
  }
23
+ plan.disconnect!
23
24
  expect(steps_run).to include 'a'
24
25
  expect(steps_run).to include 'b'
25
26
  expect(steps_run).to include 'c'
@@ -34,6 +35,7 @@ describe 'misc forklift core' do
34
35
  plan.step("b"){ steps_run << 'b' }
35
36
  plan.step("c"){ steps_run << 'c' }
36
37
  }
38
+ plan.disconnect!
37
39
  expect(steps_run).to include 'a'
38
40
  expect(steps_run).to_not include 'b'
39
41
  expect(steps_run).to include 'c'
@@ -46,6 +48,7 @@ describe 'misc forklift core' do
46
48
  plan.do! {
47
49
  plan.step("a"){ raise 'never should get here' }
48
50
  }
51
+ plan.disconnect!
49
52
  }.to raise_error SystemExit
50
53
  end
51
54
  end
metadata CHANGED
@@ -1,124 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forklift_etl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.12
5
- prerelease:
4
+ version: 1.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Evan Tahler
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-12-31 00:00:00.000000000 Z
11
+ date: 2015-01-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: activesupport
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '4.0'
22
- - - ! '>='
20
+ - - ">="
23
21
  - !ruby/object:Gem::Version
24
22
  version: 4.0.0
25
23
  type: :runtime
26
24
  prerelease: false
27
25
  version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
26
  requirements:
30
- - - ~>
27
+ - - "~>"
31
28
  - !ruby/object:Gem::Version
32
29
  version: '4.0'
33
- - - ! '>='
30
+ - - ">="
34
31
  - !ruby/object:Gem::Version
35
32
  version: 4.0.0
36
33
  - !ruby/object:Gem::Dependency
37
34
  name: mysql2
38
35
  requirement: !ruby/object:Gem::Requirement
39
- none: false
40
36
  requirements:
41
- - - ~>
37
+ - - "~>"
42
38
  - !ruby/object:Gem::Version
43
39
  version: '0.0'
44
- - - ! '>='
40
+ - - ">="
45
41
  - !ruby/object:Gem::Version
46
42
  version: 0.0.1
47
43
  type: :runtime
48
44
  prerelease: false
49
45
  version_requirements: !ruby/object:Gem::Requirement
50
- none: false
51
46
  requirements:
52
- - - ~>
47
+ - - "~>"
53
48
  - !ruby/object:Gem::Version
54
49
  version: '0.0'
55
- - - ! '>='
50
+ - - ">="
56
51
  - !ruby/object:Gem::Version
57
52
  version: 0.0.1
58
53
  - !ruby/object:Gem::Dependency
59
54
  name: elasticsearch
60
55
  requirement: !ruby/object:Gem::Requirement
61
- none: false
62
56
  requirements:
63
- - - ~>
57
+ - - "~>"
64
58
  - !ruby/object:Gem::Version
65
59
  version: '1.0'
66
- - - ! '>='
60
+ - - ">="
67
61
  - !ruby/object:Gem::Version
68
62
  version: 1.0.0
69
63
  type: :runtime
70
64
  prerelease: false
71
65
  version_requirements: !ruby/object:Gem::Requirement
72
- none: false
73
66
  requirements:
74
- - - ~>
67
+ - - "~>"
75
68
  - !ruby/object:Gem::Version
76
69
  version: '1.0'
77
- - - ! '>='
70
+ - - ">="
78
71
  - !ruby/object:Gem::Version
79
72
  version: 1.0.0
80
73
  - !ruby/object:Gem::Dependency
81
74
  name: pony
82
75
  requirement: !ruby/object:Gem::Requirement
83
- none: false
84
76
  requirements:
85
- - - ~>
77
+ - - "~>"
86
78
  - !ruby/object:Gem::Version
87
79
  version: '1.0'
88
- - - ! '>='
80
+ - - ">="
89
81
  - !ruby/object:Gem::Version
90
82
  version: 1.0.0
91
83
  type: :runtime
92
84
  prerelease: false
93
85
  version_requirements: !ruby/object:Gem::Requirement
94
- none: false
95
86
  requirements:
96
- - - ~>
87
+ - - "~>"
97
88
  - !ruby/object:Gem::Version
98
89
  version: '1.0'
99
- - - ! '>='
90
+ - - ">="
100
91
  - !ruby/object:Gem::Version
101
92
  version: 1.0.0
102
93
  - !ruby/object:Gem::Dependency
103
94
  name: lumberjack
104
95
  requirement: !ruby/object:Gem::Requirement
105
- none: false
106
96
  requirements:
107
- - - ~>
97
+ - - "~>"
108
98
  - !ruby/object:Gem::Version
109
99
  version: '1.0'
110
- - - ! '>='
100
+ - - ">="
111
101
  - !ruby/object:Gem::Version
112
102
  version: 1.0.0
113
103
  type: :runtime
114
104
  prerelease: false
115
105
  version_requirements: !ruby/object:Gem::Requirement
116
- none: false
117
106
  requirements:
118
- - - ~>
107
+ - - "~>"
119
108
  - !ruby/object:Gem::Version
120
109
  version: '1.0'
121
- - - ! '>='
110
+ - - ">="
122
111
  - !ruby/object:Gem::Version
123
112
  version: 1.0.0
124
113
  description: A collection of ETL tools and patterns for mysql and elasticsearch.
@@ -129,9 +118,9 @@ executables:
129
118
  extensions: []
130
119
  extra_rdoc_files: []
131
120
  files:
132
- - .gitignore
133
- - .rbenv-version
134
- - .travis.yml
121
+ - ".gitignore"
122
+ - ".ruby-version"
123
+ - ".travis.yml"
135
124
  - Gemfile
136
125
  - Gemfile.lock
137
126
  - LICENSE.txt
@@ -180,6 +169,7 @@ files:
180
169
  - spec/integration/multi_transport_spec.rb
181
170
  - spec/integration/mysql_patterns_spec.rb
182
171
  - spec/integration/mysql_spec.rb
172
+ - spec/integration/transformations_spec.rb
183
173
  - spec/spec_helper.rb
184
174
  - spec/support/dumps/csv/source.csv
185
175
  - spec/support/dumps/elasticsearch/forklift_test.json
@@ -189,6 +179,8 @@ files:
189
179
  - spec/support/spec_plan.rb
190
180
  - spec/support/spec_seeds.rb
191
181
  - spec/template/spec_email_template.erb
182
+ - spec/template/spec_user_transformation.rb
183
+ - spec/template/spec_user_transformation.sql
192
184
  - spec/unit/connection/mysql_spec.rb
193
185
  - spec/unit/misc/email_spec.rb
194
186
  - spec/unit/misc/error_spec.rb
@@ -202,28 +194,27 @@ files:
202
194
  homepage: https://github.com/taskrabbit/forklift
203
195
  licenses:
204
196
  - MIT
197
+ metadata: {}
205
198
  post_install_message:
206
199
  rdoc_options: []
207
200
  require_paths:
208
201
  - lib
209
202
  required_ruby_version: !ruby/object:Gem::Requirement
210
- none: false
211
203
  requirements:
212
- - - ! '>='
204
+ - - ">="
213
205
  - !ruby/object:Gem::Version
214
206
  version: '0'
215
207
  required_rubygems_version: !ruby/object:Gem::Requirement
216
- none: false
217
208
  requirements:
218
- - - ! '>='
209
+ - - ">="
219
210
  - !ruby/object:Gem::Version
220
211
  version: '0'
221
212
  requirements: []
222
213
  rubyforge_project: forklift_etl
223
- rubygems_version: 1.8.23
214
+ rubygems_version: 2.2.2
224
215
  signing_key:
225
- specification_version: 3
226
- summary: ! 'Forklift: Moving big databases around. A ruby ETL tool.'
216
+ specification_version: 4
217
+ summary: 'Forklift: Moving big databases around. A ruby ETL tool.'
227
218
  test_files:
228
219
  - spec/config/connections/csv/forklift_test_destination.yml
229
220
  - spec/config/connections/csv/forklift_test_source.yml
@@ -240,6 +231,7 @@ test_files:
240
231
  - spec/integration/multi_transport_spec.rb
241
232
  - spec/integration/mysql_patterns_spec.rb
242
233
  - spec/integration/mysql_spec.rb
234
+ - spec/integration/transformations_spec.rb
243
235
  - spec/spec_helper.rb
244
236
  - spec/support/dumps/csv/source.csv
245
237
  - spec/support/dumps/elasticsearch/forklift_test.json
@@ -249,8 +241,11 @@ test_files:
249
241
  - spec/support/spec_plan.rb
250
242
  - spec/support/spec_seeds.rb
251
243
  - spec/template/spec_email_template.erb
244
+ - spec/template/spec_user_transformation.rb
245
+ - spec/template/spec_user_transformation.sql
252
246
  - spec/unit/connection/mysql_spec.rb
253
247
  - spec/unit/misc/email_spec.rb
254
248
  - spec/unit/misc/error_spec.rb
255
249
  - spec/unit/misc/pid_spec.rb
256
250
  - spec/unit/misc/step_spec.rb
251
+ has_rdoc:
data/.rbenv-version DELETED
@@ -1 +0,0 @@
1
- 1.9.3-p194