beetle_etl 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.
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