beetle_etl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.travis.yml +12 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +31 -0
  7. data/Rakefile +5 -0
  8. data/beetle_etl.gemspec +30 -0
  9. data/lib/beetle_etl.rb +85 -0
  10. data/lib/beetle_etl/dsl/dsl.rb +37 -0
  11. data/lib/beetle_etl/dsl/transformation.rb +26 -0
  12. data/lib/beetle_etl/dsl/transformation_loader.rb +22 -0
  13. data/lib/beetle_etl/import.rb +37 -0
  14. data/lib/beetle_etl/state.rb +67 -0
  15. data/lib/beetle_etl/steps/assign_ids.rb +54 -0
  16. data/lib/beetle_etl/steps/load.rb +108 -0
  17. data/lib/beetle_etl/steps/map_relations.rb +31 -0
  18. data/lib/beetle_etl/steps/step.rb +42 -0
  19. data/lib/beetle_etl/steps/table_diff.rb +155 -0
  20. data/lib/beetle_etl/steps/transform.rb +22 -0
  21. data/lib/beetle_etl/task_runner/dependency_resolver.rb +39 -0
  22. data/lib/beetle_etl/task_runner/task_runner.rb +64 -0
  23. data/lib/beetle_etl/version.rb +3 -0
  24. data/script/postgres +12 -0
  25. data/spec/beetle_etl_spec.rb +70 -0
  26. data/spec/dependency_resolver_spec.rb +57 -0
  27. data/spec/dsl/dsl_spec.rb +44 -0
  28. data/spec/dsl/transformation_loader_spec.rb +51 -0
  29. data/spec/dsl/transformation_spec.rb +54 -0
  30. data/spec/feature/example_schema.rb +192 -0
  31. data/spec/feature/example_transform.rb +37 -0
  32. data/spec/feature/feature_spec.rb +48 -0
  33. data/spec/import_spec.rb +7 -0
  34. data/spec/spec_helper.rb +25 -0
  35. data/spec/state_spec.rb +124 -0
  36. data/spec/steps/assign_ids_spec.rb +107 -0
  37. data/spec/steps/load_spec.rb +148 -0
  38. data/spec/steps/map_relations_spec.rb +92 -0
  39. data/spec/steps/step_spec.rb +37 -0
  40. data/spec/steps/table_diff_spec.rb +183 -0
  41. data/spec/steps/transform_spec.rb +34 -0
  42. data/spec/support/database.yml.example +9 -0
  43. data/spec/support/database.yml.travis +4 -0
  44. data/spec/support/database_helpers.rb +58 -0
  45. metadata +220 -0
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+
3
+ module BeetleETL
4
+ describe MapRelations do
5
+
6
+ let(:run_id) { 1 }
7
+ let(:previous_run_id) { 5000 }
8
+
9
+ before do
10
+ BeetleETL.configure do |config|
11
+ config.stage_schema = 'stage'
12
+ config.external_source = 'my_source'
13
+ config.database = test_database
14
+ end
15
+
16
+ allow(BeetleETL).to receive(:state) { double(:state, run_id: run_id) }
17
+
18
+ test_database.create_schema(:stage)
19
+ test_database.create_table(:stage__dependee_a) do
20
+ Integer :import_run_id
21
+ Integer :id
22
+ String :external_id, size: 255
23
+ end
24
+
25
+ test_database.create_table(:stage__dependee_b) do
26
+ Integer :import_run_id
27
+ Integer :id
28
+ String :external_id, size: 255
29
+ end
30
+
31
+ test_database.create_table(:stage__depender) do
32
+ Integer :import_run_id
33
+ String :external_id, size: 255
34
+
35
+ String :external_dependee_a_id
36
+ Integer :dependee_a_id
37
+
38
+ String :external_dependee_b_id
39
+ Integer :dependee_b_id
40
+ end
41
+ end
42
+
43
+ describe '#depenencies' do
44
+ it 'depends on Transform of the same table and AssignIds of its dependees' do
45
+ relations = {
46
+ dependee_a_id: :dependee_a,
47
+ dependee_b_id: :dependee_b,
48
+ }
49
+
50
+ expect(MapRelations.new(:depender, relations).dependencies).to eql(
51
+ [
52
+ 'dependee_a: AssignIds',
53
+ 'dependee_b: AssignIds',
54
+ 'depender: Transform',
55
+ ].to_set
56
+ )
57
+ end
58
+ end
59
+
60
+ describe '#run' do
61
+ it 'maps external foreign key references to id references ' do
62
+ insert_into(:stage__dependee_a).values(
63
+ [ :import_run_id , :id , :external_id ] ,
64
+ [ run_id , 1 , 'a_id' ] ,
65
+ [ previous_run_id , 2 , 'a_id' ] ,
66
+ )
67
+
68
+ insert_into(:stage__dependee_b).values(
69
+ [ :import_run_id , :id , :external_id ] ,
70
+ [ run_id , 26 , 'b_id' ] ,
71
+ )
72
+
73
+ insert_into(:stage__depender).values(
74
+ [ :import_run_id , :external_dependee_a_id , :external_dependee_b_id ] ,
75
+ [ run_id , 'a_id' , 'b_id' ] ,
76
+ )
77
+
78
+ relations = {
79
+ dependee_a_id: :dependee_a,
80
+ dependee_b_id: :dependee_b,
81
+ }
82
+
83
+ MapRelations.new(:depender, relations).run
84
+
85
+ expect(:stage__depender).to have_values(
86
+ [ :import_run_id , :dependee_a_id , :dependee_b_id ] ,
87
+ [ run_id , 1 , 26 ] ,
88
+ )
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ module BeetleETL
4
+ describe Step do
5
+
6
+ subject { Step.new(:example_table) }
7
+ FooStep = Class.new(Step)
8
+
9
+ describe '.step_name' do
10
+ it 'returns the steps name' do
11
+ expect(Step.step_name(:example_table)).to eql('example_table: Step')
12
+ end
13
+
14
+ it 'returns the step name of inheriting steps' do
15
+ expect(FooStep.step_name(:foo_table)).to eql('foo_table: FooStep')
16
+ end
17
+ end
18
+
19
+ describe '#name' do
20
+ it 'returns the steps name' do
21
+ expect(Step.new(:example_table).name).to eql('example_table: Step')
22
+ end
23
+
24
+ it 'returns the step name of inheriting steps' do
25
+ expect(FooStep.new(:foo_table).name).to eql('foo_table: FooStep')
26
+ end
27
+ end
28
+
29
+ describe '#dependencies' do
30
+ it 'raises an exception' do
31
+ expect { subject.dependencies }.to raise_error(DependenciesNotDefinedError)
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,183 @@
1
+ require 'spec_helper'
2
+
3
+ require 'active_support/core_ext/date/calculations'
4
+ require 'active_support/core_ext/numeric/time'
5
+
6
+ module BeetleETL
7
+ describe TableDiff do
8
+
9
+ let(:run_id) { 1 }
10
+ let(:external_source) { 'my_source' }
11
+ subject { TableDiff.new(:example_table) }
12
+
13
+ before do
14
+ BeetleETL.configure do |config|
15
+ config.stage_schema = 'stage'
16
+ config.external_source = external_source
17
+ config.database = test_database
18
+ end
19
+
20
+ allow(BeetleETL).to receive(:state) { double(:state, run_id: run_id) }
21
+
22
+ test_database.create_schema(:stage)
23
+ test_database.create_table(:stage__example_table) do
24
+ Integer :import_run_id
25
+ String :external_id, size: 255
26
+ String :transition, size: 20
27
+
28
+ String :external_foo_id, size: 255
29
+ Integer :foo_id
30
+
31
+ String :payload, size: 255
32
+ end
33
+
34
+ test_database.create_table(:example_table) do
35
+ Integer :id
36
+ String :external_id, size: 255
37
+ String :external_source, size: 255
38
+ DateTime :deleted_at
39
+
40
+ String :payload, size: 255
41
+ String :ignored_attribute, size: 255
42
+ Integer :foo_id
43
+ end
44
+ end
45
+
46
+ describe '#depenencies' do
47
+ it 'depends on MapRelations of the same table' do
48
+ expect(subject.dependencies).to eql(['example_table: MapRelations'].to_set)
49
+ end
50
+ end
51
+
52
+ describe '#run' do
53
+ it 'runs all transitions' do
54
+ %w(create keep update delete undelete).each do |transition|
55
+ expect(subject).to receive(:"transition_#{transition}")
56
+ end
57
+
58
+ subject.run
59
+ end
60
+ end
61
+
62
+ describe '#transition_create' do
63
+ it 'assigns CREATE to new records' do
64
+
65
+ insert_into(:example_table).values(
66
+ [ :external_id , :external_source , :payload , :ignored_attribute , :foo_id , :deleted_at ] ,
67
+ [ 'existing' , external_source , 'existing content' , 'ignored content' , 1 , nil ] ,
68
+ [ 'deleted' , external_source , 'deleted content' , 'ignored content' , 2 , 1.day.ago ] ,
69
+ )
70
+
71
+ insert_into(:stage__example_table).values(
72
+ [ :import_run_id , :external_id ] ,
73
+ [ run_id , 'created' ] ,
74
+ [ run_id , 'existing' ] ,
75
+ )
76
+
77
+ subject.transition_create
78
+
79
+ expect(:stage__example_table).to have_values(
80
+ [ :import_run_id , :external_id , :transition ] ,
81
+ [ run_id , 'created' , 'CREATE' ] ,
82
+ [ run_id , 'existing' , nil ] ,
83
+ )
84
+ end
85
+ end
86
+
87
+ describe 'transition_keep' do
88
+ it 'assigns KEEP if the record already exists and is not deleted, comparing all columns
89
+ except externald_*_id columns and columns not contained in the stage table' do
90
+
91
+ insert_into(:example_table).values(
92
+ [ :external_id , :external_source , :payload , :ignored_attribute , :foo_id , :deleted_at ] ,
93
+ [ 'existing' , external_source , 'existing content' , 'ignored content' , 1 , nil ] ,
94
+ [ 'deleted' , external_source , 'deleted content' , 'ignored content' , 2 , 1.day.ago ] ,
95
+ )
96
+
97
+ insert_into(:stage__example_table).values(
98
+ [ :import_run_id , :external_id , :payload , :foo_id , :external_foo_id ] ,
99
+ [ run_id , 'existing' , 'existing content' , 1 , 'ignored column' ] ,
100
+ [ run_id , 'deleted' , 'deleted content' , 2 , 'ignored column' ] ,
101
+ )
102
+
103
+ subject.transition_keep
104
+
105
+ expect(:stage__example_table).to have_values(
106
+ [ :import_run_id , :external_id , :transition ] ,
107
+ [ run_id , 'existing' , 'KEEP' ] ,
108
+ [ run_id , 'deleted' , nil ] ,
109
+ )
110
+ end
111
+ end
112
+
113
+ describe '#transition_update' do
114
+ it 'assigns UPDATE to non-deleted records with changed values comparing all columns
115
+ except externald_*_id columns and columns not contained in the stage table' do
116
+
117
+ insert_into(:example_table).values(
118
+ [ :external_id , :external_source , :payload , :ignored_attribute , :foo_id , :deleted_at ] ,
119
+ [ 'existing_1' , external_source , 'existing content' , 'ignored content' , 1 , nil ] ,
120
+ [ 'existing_2' , external_source , 'existing content' , 'ignored content' , 2 , nil ] ,
121
+ [ 'deleted' , external_source , 'deleted content' , 'ignored content' , 3 , 1.day.ago ] ,
122
+ )
123
+
124
+ insert_into(:stage__example_table).values(
125
+ [ :import_run_id , :external_id , :payload , :foo_id , :external_foo_id ] ,
126
+ [ run_id , 'existing_1' , 'updated content' , 1 , 'ignored_column' ] ,
127
+ [ run_id , 'existing_2' , 'existing content' , 4 , 'ignored_column' ] ,
128
+ [ run_id , 'deleted' , 'updated content' , 3 , 'ignored_column' ] ,
129
+ )
130
+
131
+ subject.transition_update
132
+
133
+ expect(:stage__example_table).to have_values(
134
+ [ :import_run_id , :external_id , :transition ] ,
135
+ [ run_id , 'existing_1' , 'UPDATE' ] ,
136
+ [ run_id , 'existing_2' , 'UPDATE' ] ,
137
+ [ run_id , 'deleted' , nil ] ,
138
+ )
139
+ end
140
+ end
141
+
142
+ describe 'transition_delete' do
143
+ it 'creates records with DELETE that no loger exist in the stage table' do
144
+ insert_into(:example_table).values(
145
+ [ :external_id , :external_source , :payload , :ignored_attribute , :foo_id , :deleted_at ] ,
146
+ [ 'existing' , external_source , 'existing content' , 'ignored content' , 1 , nil ] ,
147
+ [ 'deleted' , external_source , 'deleted content' , 'ignored content' , 2 , 1.day.ago ] ,
148
+ )
149
+
150
+ subject.transition_delete
151
+
152
+ expect(:stage__example_table).to have_values(
153
+ [ :import_run_id , :external_id , :transition ] ,
154
+ [ run_id , 'existing' , 'DELETE' ] ,
155
+ )
156
+ end
157
+ end
158
+
159
+ describe 'transition_undelete' do
160
+ it 'assigns UNDELETE to previously deleted records' do
161
+ insert_into(:example_table).values(
162
+ [ :external_id , :external_source , :payload , :ignored_attribute , :foo_id , :deleted_at ] ,
163
+ [ 'existing' , external_source , 'existing content' , 'ignored content' , 1 , nil ] ,
164
+ [ 'deleted' , external_source , 'deleted content' , 'ignored content' , 2 , 1.day.ago ] ,
165
+ )
166
+
167
+ insert_into(:stage__example_table).values(
168
+ [ :import_run_id , :external_id , :payload , :foo_id , :external_foo_id ] ,
169
+ [ run_id , 'existing' , 'updated content' , 1 , 'ignored_column' ] ,
170
+ [ run_id , 'deleted' , 'updated content' , 2 , 'ignored_column' ] ,
171
+ )
172
+
173
+ subject.transition_undelete
174
+
175
+ expect(:stage__example_table).to have_values(
176
+ [ :import_run_id , :external_id , :transition ] ,
177
+ [ run_id , 'existing' , nil ] ,
178
+ [ run_id , 'deleted' , 'UNDELETE' ] ,
179
+ )
180
+ end
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ module BeetleETL
4
+ describe Transform do
5
+
6
+ let(:query) { double(:query) }
7
+ subject do
8
+ deps = [:some_table, :some_other_table].to_set
9
+ Transform.new(:example_table, deps, query)
10
+ end
11
+
12
+ describe '#dependencies' do
13
+ it 'depends on Transform of all dependencies' do
14
+ expect(subject.dependencies).to eql(
15
+ [
16
+ 'some_table: Transform',
17
+ 'some_other_table: Transform',
18
+ ].to_set
19
+ )
20
+ end
21
+ end
22
+
23
+ describe '#run' do
24
+ it 'runs a query in the database' do
25
+ database = double(:database)
26
+ BeetleETL.configure { |config| config.database = database }
27
+
28
+ expect(database).to receive(:run).with(query)
29
+
30
+ subject.run
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ adapter: 'postgres'
2
+ encoding: utf8
3
+ host: localhost
4
+ database: beetle_etl_test
5
+ username: ''
6
+ password: ''
7
+ pool: 5
8
+ pool_timeout: 360
9
+ connect_timeout: 360
@@ -0,0 +1,4 @@
1
+ adapter: 'postgres'
2
+ encoding: utf8
3
+ database: travis_ci_test
4
+ username: postgres
@@ -0,0 +1,58 @@
1
+ require 'sequel'
2
+ require 'yaml'
3
+ require 'rspec/expectations'
4
+
5
+ module SpecSupport
6
+ module DatabaseHelpers
7
+
8
+ module Test
9
+ class Table
10
+ def initialize dataset
11
+ @dataset = dataset
12
+ end
13
+
14
+ def values(*data)
15
+ columns = data[0]
16
+ values = data[1..-1]
17
+ @dataset.import(columns, values)
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_database
23
+ @database ||= begin
24
+ config_path = File.expand_path('./database.yml', File.dirname(__FILE__))
25
+ config = File.read(config_path)
26
+ Sequel.connect(YAML.load(config))
27
+ end
28
+ end
29
+
30
+ def insert_into(table_description)
31
+ dataset = test_database[table_description]
32
+ Test::Table.new(dataset)
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ RSpec::Matchers.define :have_values do |*rows|
39
+ match do |table_description|
40
+ dataset = test_database[table_description]
41
+
42
+ columns = rows[0].map(&:to_sym)
43
+ values = rows[1..-1]
44
+
45
+ begin
46
+ expect{dataset.select(columns).all}.not_to raise_error
47
+ expect(dataset.map(columns)).to match_array(values)
48
+ true
49
+ rescue RSpec::Expectations::ExpectationNotMetError => error
50
+ @expectation_not_met_error = error
51
+ false
52
+ end
53
+ end
54
+
55
+ failure_message do |dataset|
56
+ @expectation_not_met_error.message
57
+ end
58
+ end
metadata ADDED
@@ -0,0 +1,220 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: beetle_etl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Luciano Maiwald
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sequel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 4.13.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 4.13.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: celluloid
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.15.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.15.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: pg
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: codeclimate-test-reporter
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Taking care of synchronizing external data with referential data in your
126
+ application.
127
+ email:
128
+ - luciano.maiwald@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .travis.yml
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - beetle_etl.gemspec
140
+ - lib/beetle_etl.rb
141
+ - lib/beetle_etl/dsl/dsl.rb
142
+ - lib/beetle_etl/dsl/transformation.rb
143
+ - lib/beetle_etl/dsl/transformation_loader.rb
144
+ - lib/beetle_etl/import.rb
145
+ - lib/beetle_etl/state.rb
146
+ - lib/beetle_etl/steps/assign_ids.rb
147
+ - lib/beetle_etl/steps/load.rb
148
+ - lib/beetle_etl/steps/map_relations.rb
149
+ - lib/beetle_etl/steps/step.rb
150
+ - lib/beetle_etl/steps/table_diff.rb
151
+ - lib/beetle_etl/steps/transform.rb
152
+ - lib/beetle_etl/task_runner/dependency_resolver.rb
153
+ - lib/beetle_etl/task_runner/task_runner.rb
154
+ - lib/beetle_etl/version.rb
155
+ - script/postgres
156
+ - spec/beetle_etl_spec.rb
157
+ - spec/dependency_resolver_spec.rb
158
+ - spec/dsl/dsl_spec.rb
159
+ - spec/dsl/transformation_loader_spec.rb
160
+ - spec/dsl/transformation_spec.rb
161
+ - spec/feature/example_schema.rb
162
+ - spec/feature/example_transform.rb
163
+ - spec/feature/feature_spec.rb
164
+ - spec/import_spec.rb
165
+ - spec/spec_helper.rb
166
+ - spec/state_spec.rb
167
+ - spec/steps/assign_ids_spec.rb
168
+ - spec/steps/load_spec.rb
169
+ - spec/steps/map_relations_spec.rb
170
+ - spec/steps/step_spec.rb
171
+ - spec/steps/table_diff_spec.rb
172
+ - spec/steps/transform_spec.rb
173
+ - spec/support/database.yml.example
174
+ - spec/support/database.yml.travis
175
+ - spec/support/database_helpers.rb
176
+ homepage: https://github.com/maiwald/beetle_etl
177
+ licenses:
178
+ - MIT
179
+ metadata: {}
180
+ post_install_message:
181
+ rdoc_options: []
182
+ require_paths:
183
+ - lib
184
+ required_ruby_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - '>='
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ required_rubygems_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - '>='
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ requirements: []
195
+ rubyforge_project:
196
+ rubygems_version: 2.1.11
197
+ signing_key:
198
+ specification_version: 4
199
+ summary: BeetleETL helps you with your recurring ETL imports.
200
+ test_files:
201
+ - spec/beetle_etl_spec.rb
202
+ - spec/dependency_resolver_spec.rb
203
+ - spec/dsl/dsl_spec.rb
204
+ - spec/dsl/transformation_loader_spec.rb
205
+ - spec/dsl/transformation_spec.rb
206
+ - spec/feature/example_schema.rb
207
+ - spec/feature/example_transform.rb
208
+ - spec/feature/feature_spec.rb
209
+ - spec/import_spec.rb
210
+ - spec/spec_helper.rb
211
+ - spec/state_spec.rb
212
+ - spec/steps/assign_ids_spec.rb
213
+ - spec/steps/load_spec.rb
214
+ - spec/steps/map_relations_spec.rb
215
+ - spec/steps/step_spec.rb
216
+ - spec/steps/table_diff_spec.rb
217
+ - spec/steps/transform_spec.rb
218
+ - spec/support/database.yml.example
219
+ - spec/support/database.yml.travis
220
+ - spec/support/database_helpers.rb