migratrix 0.0.9 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/migratrix.rb +62 -6
- data/lib/migratrix/exceptions.rb +4 -1
- data/lib/migratrix/{extractors → extractions}/active_record.rb +14 -10
- data/lib/migratrix/{extractors/extractor.rb → extractions/extraction.rb} +21 -20
- data/lib/migratrix/loads/load.rb +43 -0
- data/lib/migratrix/loads/yaml.rb +15 -0
- data/lib/migratrix/migration.rb +115 -27
- data/lib/migratrix/migratrix.rb +43 -84
- data/lib/migratrix/registry.rb +20 -0
- data/lib/migratrix/transforms/map.rb +57 -0
- data/lib/migratrix/transforms/transform.rb +268 -0
- data/lib/migratrix/valid_options.rb +22 -0
- data/lib/patches/object_ext.rb +0 -4
- data/spec/fixtures/migrations/marbles_migration.rb +6 -4
- data/spec/lib/migratrix/{loggable_spec.rb → _loggable_spec.rb} +0 -0
- data/spec/lib/migratrix/extractions/active_record_spec.rb +146 -0
- data/spec/lib/migratrix/extractions/extraction_spec.rb +71 -0
- data/spec/lib/migratrix/loads/load_spec.rb +59 -0
- data/spec/lib/migratrix/loads/yaml_spec.rb +39 -0
- data/spec/lib/migratrix/migration_spec.rb +195 -27
- data/spec/lib/migratrix/migratrix_spec.rb +57 -85
- data/spec/lib/migratrix/registry_spec.rb +28 -0
- data/spec/lib/migratrix/transforms/map_spec.rb +55 -0
- data/spec/lib/migratrix/transforms/transform_spec.rb +134 -0
- data/spec/lib/migratrix_spec.rb +98 -0
- data/spec/lib/patches/object_ext_spec.rb +0 -7
- data/spec/spec_helper.rb +18 -13
- metadata +21 -10
- data/spec/lib/migratrix/extractors/active_record_spec.rb +0 -43
- data/spec/lib/migratrix/extractors/extractor_spec.rb +0 -63
- data/spec/lib/migratrix_module_spec.rb +0 -63
@@ -1,106 +1,83 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
it "exists (sanity check)" do
|
7
|
-
Migratrix.should_not be_nil
|
8
|
-
Migratrix.class.should == Module
|
9
|
-
Migratrix.class.should_not == Class
|
10
|
-
Migratrix::Migratrix.class.should_not == Module
|
11
|
-
Migratrix::Migratrix.class.should == Class
|
12
|
-
Migratrix.const_defined?("Migratrix").should be_true
|
13
|
-
end
|
14
|
-
|
15
|
-
describe "MigrationRegistry (needs to be extracted)" do
|
16
|
-
before do
|
17
|
-
reset_migratrix! migratrix
|
18
|
-
Migratrix.class_eval("class PantsMigration < Migration; end")
|
19
|
-
migratrix.register_migration "PantsMigration", Migratrix::PantsMigration
|
20
|
-
end
|
21
|
-
|
22
|
-
it "can register migrations by name" do
|
23
|
-
migratrix.loaded?("PantsMigration").should be_true
|
24
|
-
Migratrix.const_defined?("PantsMigration").should be_true
|
25
|
-
end
|
3
|
+
class TestExtraction < Migratrix::Extractions::Extraction
|
4
|
+
end
|
26
5
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
6
|
+
class TestTransform < Migratrix::Transforms::Transform
|
7
|
+
end
|
30
8
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
end
|
9
|
+
class TestLoad < Migratrix::Loads::Load
|
10
|
+
end
|
35
11
|
|
36
|
-
|
37
|
-
|
38
|
-
migratrix.migrations_path.should == ROOT + "db/legacy"
|
39
|
-
end
|
12
|
+
describe Migratrix::Migratrix do
|
13
|
+
let (:migratrix) { Migratrix::Migratrix.new }
|
40
14
|
|
41
|
-
|
42
|
-
|
43
|
-
|
15
|
+
describe "sanity check cat" do
|
16
|
+
it "is sanity checked" do
|
17
|
+
Migratrix.should_not be_nil
|
18
|
+
Migratrix.class.should == Module
|
19
|
+
Migratrix.class.should_not == Class
|
20
|
+
Migratrix::Migratrix.class.should_not == Module
|
21
|
+
Migratrix::Migratrix.class.should == Class
|
22
|
+
Migratrix.const_defined?("Migratrix").should be_true
|
44
23
|
end
|
45
24
|
end
|
46
25
|
|
47
|
-
describe "
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
26
|
+
describe "Migration Component Registry" do
|
27
|
+
describe ".register_extraction" do
|
28
|
+
before do
|
29
|
+
Migratrix::Migratrix.register_extraction :test_extraction, TestExtraction, { :source => Object }
|
30
|
+
end
|
52
31
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
options.should_not have_key("pants")
|
58
|
-
end
|
59
|
-
end
|
32
|
+
it "registers the extraction" do
|
33
|
+
Migratrix::Migratrix.extractions.registered?(:test_extraction).should be_true
|
34
|
+
Migratrix::Migratrix.extractions.class_for(:test_extraction).should == TestExtraction
|
35
|
+
end
|
60
36
|
|
61
|
-
|
62
|
-
|
63
|
-
|
37
|
+
it "creates the extraction with given options" do
|
38
|
+
extraction = TestExtraction.new :test
|
39
|
+
Migratrix::Migratrix.extractions.registered?(:test_extraction).should be_true
|
40
|
+
Migratrix::Migratrix.extractions.class_for(:test_extraction).should == TestExtraction
|
41
|
+
end
|
64
42
|
end
|
65
43
|
|
66
|
-
|
67
|
-
|
68
|
-
|
44
|
+
describe ".register_transform" do
|
45
|
+
before do
|
46
|
+
Migratrix::Migratrix.register_transform :test_transform, TestTransform, { :source => Object }
|
47
|
+
end
|
69
48
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
end
|
49
|
+
it "registers the transform" do
|
50
|
+
Migratrix::Migratrix.transforms.registered?(:test_transform).should be_true
|
51
|
+
Migratrix::Migratrix.transforms.class_for(:test_transform).should == TestTransform
|
52
|
+
end
|
75
53
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
54
|
+
it "creates the transform with given options" do
|
55
|
+
transform = TestTransform.new :monkeys
|
56
|
+
Migratrix::Migratrix.transforms.registered?(:test_transform).should be_true
|
57
|
+
Migratrix::Migratrix.transforms.class_for(:test_transform).should == TestTransform
|
58
|
+
end
|
80
59
|
end
|
81
60
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
migration.options.should == { "where" => "id > 100", "limit" => "100" }
|
87
|
-
end
|
88
|
-
end
|
61
|
+
describe ".register_load" do
|
62
|
+
before do
|
63
|
+
Migratrix::Migratrix.register_load :test_load, TestLoad
|
64
|
+
end
|
89
65
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
end
|
66
|
+
it "registers the load" do
|
67
|
+
Migratrix::Migratrix.loads.registered?(:test_load).should be_true
|
68
|
+
Migratrix::Migratrix.loads.class_for(:test_load).should == TestLoad
|
69
|
+
end
|
95
70
|
|
96
|
-
|
97
|
-
|
98
|
-
|
71
|
+
it "creates the load with given options" do
|
72
|
+
load = TestLoad.new :monkeys
|
73
|
+
Migratrix::Migratrix.loads.registered?(:test_load).should be_true
|
74
|
+
Migratrix::Migratrix.loads.class_for(:test_load).should == TestLoad
|
75
|
+
end
|
99
76
|
end
|
100
77
|
end
|
101
78
|
|
102
79
|
describe "with logger as a singleton" do
|
103
|
-
let (:migration) {
|
80
|
+
let (:migration) { Migratrix::MarblesMigration.new }
|
104
81
|
let (:buffer) { StringIO.new }
|
105
82
|
|
106
83
|
def spec_all_loggers_are(this_logger)
|
@@ -111,11 +88,6 @@ describe Migratrix::Migratrix do
|
|
111
88
|
Migratrix::MarblesMigration.logger.should == this_logger
|
112
89
|
end
|
113
90
|
|
114
|
-
before do
|
115
|
-
reset_migratrix! migratrix
|
116
|
-
migratrix.migrations_path = SPEC + "fixtures/migrations"
|
117
|
-
end
|
118
|
-
|
119
91
|
describe ".logger=" do
|
120
92
|
it "sets logger globally across all Migratrices, the Migratrix module, Migrators and Models" do
|
121
93
|
logger = Migratrix::Migratrix.create_logger(buffer)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Migratrix::Registry do
|
4
|
+
describe "sanity check cat" do
|
5
|
+
it "is sanity checked" do
|
6
|
+
::Migratrix::Registry.should_not be_nil
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#register" do
|
11
|
+
let(:registry) { ::Migratrix::Registry.new }
|
12
|
+
before do
|
13
|
+
registry.register(:test, Array, 3)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "registers the class by name" do
|
17
|
+
registry.registered?(:test).should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#class_for" do
|
21
|
+
it "returns the registered class" do
|
22
|
+
registry.class_for(:test).should == Array
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestMap < Migratrix::Transforms::Map
|
4
|
+
end
|
5
|
+
|
6
|
+
describe Migratrix::Transforms::Map do
|
7
|
+
describe "sanity check cat" do
|
8
|
+
it "is sanity checked" do
|
9
|
+
Migratrix::Transforms::Map.should_not be_nil
|
10
|
+
TestMap.should_not be_nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:loggable) { TestMap.new(:loggable) }
|
15
|
+
it_should_behave_like "loggable"
|
16
|
+
|
17
|
+
describe ".local_valid_options" do
|
18
|
+
it "returns the valid set of option keys" do
|
19
|
+
Migratrix::Transforms::Map.local_valid_options.should == []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".valid_options" do
|
24
|
+
it "returns the valide set of options plus those of the superclass" do
|
25
|
+
Migratrix::Transforms::Map.valid_options.should == Migratrix::Transforms::Transform.local_valid_options
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "with pet types fixture" do
|
30
|
+
let(:extracted_pets) {
|
31
|
+
[
|
32
|
+
{ :pet_type_id => 42, :pet_species => 'Dog' },
|
33
|
+
{ :pet_type_id => 43, :pet_species => 'Cat' },
|
34
|
+
{ :pet_type_id => 44, :pet_species => 'Rat' },
|
35
|
+
{ :pet_type_id => 45, :pet_species => 'Parrot' }
|
36
|
+
]
|
37
|
+
}
|
38
|
+
let(:map) { { :id => :pet_type_id, :name => :pet_species } }
|
39
|
+
let(:expected_transform) { {
|
40
|
+
42 => { :id => 42, :name => 'Dog' },
|
41
|
+
43 => { :id => 43, :name => 'Cat' },
|
42
|
+
44 => { :id => 44, :name => 'Rat' },
|
43
|
+
45 => { :id => 45, :name => 'Parrot' }
|
44
|
+
}
|
45
|
+
}
|
46
|
+
let(:transform) { Migratrix::Transforms::Map.new(:pet_types, :transform => map) }
|
47
|
+
|
48
|
+
it "transforms data correctly" do
|
49
|
+
with_logging_to(StringIO.new) do
|
50
|
+
transform.transform(extracted_pets).should == expected_transform
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestTransform < Migratrix::Transforms::Transform
|
4
|
+
include Migratrix::Loggable
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Migratrix::Transforms::Transform do
|
8
|
+
describe "sanity check cat" do
|
9
|
+
it "is sanity checked" do
|
10
|
+
Migratrix::Transforms::Transform.should_not be_nil
|
11
|
+
TestTransform.should_not be_nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:loggable) { TestTransform.new(:loggable) }
|
16
|
+
it_should_behave_like "loggable"
|
17
|
+
|
18
|
+
describe ".local_valid_options" do
|
19
|
+
it "returns the valid set of option keys" do
|
20
|
+
Migratrix::Transforms::Transform.local_valid_options.should == [:apply_attribute, :extract_attribute, :extraction, :final_class, :finalize_object, :store_transform, :target, :transform, :transform_class, :transform_collection]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
describe "#extraction" do
|
26
|
+
it "returns extraction name when set" do
|
27
|
+
transform = Migratrix::Transforms::Transform.new(:pants_transform, { extraction: :pants_extraction })
|
28
|
+
transform.extraction.should == :pants_extraction
|
29
|
+
end
|
30
|
+
|
31
|
+
it "#returns transform name when no extraction name is set" do
|
32
|
+
transform = Migratrix::Transforms::Transform.new(:pants_transform)
|
33
|
+
transform.extraction.should == :pants_transform
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "unimplemented methods:" do
|
38
|
+
[ [:create_transformed_collection, []],
|
39
|
+
[:create_new_object, [:extracted_row]],
|
40
|
+
[:apply_attribute, [:object, :value, :attribute_or_apply]],
|
41
|
+
[:extract_attribute, [:object, :attribute_or_extract]],
|
42
|
+
[:store_transformed_object, [:object, :collection]] ].each do |method, args|
|
43
|
+
describe "#{method}(#{args.map(&:inspect)*','})" do
|
44
|
+
let(:object_with_not_implemented_methods) { Migratrix::Transforms::Transform.new(:brain_damaged_transform) }
|
45
|
+
it "raises NotImplementedError" do
|
46
|
+
lambda { object_with_not_implemented_methods.send(method, *args) }.should raise_error(NotImplementedError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "TypeError methods" do
|
53
|
+
[:transform_collection, :transform_class, :extract_attribute, :apply_attribute, :final_class, :finalize_object, :store_transformed_object].each do |method|
|
54
|
+
describe "With #{method} set to a string" do
|
55
|
+
let(:transform_options) { {
|
56
|
+
extraction: :test_stream,
|
57
|
+
transform: { id: :src_id, name: :src_name },
|
58
|
+
transform_collection: Array,
|
59
|
+
transform_class: Hash,
|
60
|
+
extract_attribute: ->(object, attribute) { object[attribute] },
|
61
|
+
apply_attribute: ->(object, attribute, value) { object[attribute] = value },
|
62
|
+
final_class: Set,
|
63
|
+
finalize_object: ->(object) { object.to_a },
|
64
|
+
store_transformed_object: :<<
|
65
|
+
}.merge( method => "cheese")
|
66
|
+
}
|
67
|
+
let(:transform) { TestTransform.new :test, transform_options }
|
68
|
+
let(:test_stream) { [{src_id: 42, src_name: "Alice"}, {src_id: 43, src_name: "Bob"} ] }
|
69
|
+
let(:extractions) { { test_stream: mock("extraction", name: "test_stream", extract: test_stream )}}
|
70
|
+
|
71
|
+
it "should raise TypeError" do
|
72
|
+
lambda { transform.transform(test_stream) }.should raise_error(TypeError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "with Proc options" do
|
79
|
+
let(:transform) { TestTransform.new :test, {
|
80
|
+
extraction: :test_stream,
|
81
|
+
transform: { id: :src_id, name: :src_name },
|
82
|
+
transform_collection: ->{ Array.new },
|
83
|
+
transform_class: ->(row) { Hash.new },
|
84
|
+
extract_attribute: ->(object, attribute) { object[attribute] },
|
85
|
+
apply_attribute: ->(object, attribute, value) { object[attribute] = value },
|
86
|
+
final_class: Set,
|
87
|
+
finalize_object: ->(object) { object.to_a },
|
88
|
+
store_transformed_object: ->(object, collection) { collection << object }
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
let(:test_stream) { [{src_id: 42, src_name: "Alice"}, {src_id: 43, src_name: "Bob"} ] }
|
93
|
+
let(:extractions) { { test_stream: mock("extraction", name: "test_stream", extract: test_stream )}}
|
94
|
+
|
95
|
+
before do
|
96
|
+
TestTransform.stub!(:extractions).and_return(extractions)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should delegate to procs" do
|
100
|
+
transform.transform(test_stream).should == [
|
101
|
+
Set.new([[:id, 42], [:name, "Alice"]]),
|
102
|
+
Set.new([[:id, 43], [:name, "Bob"]])
|
103
|
+
]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe "with symbol and class options" do
|
108
|
+
let(:transform) { TestTransform.new :test, {
|
109
|
+
extraction: :test_stream,
|
110
|
+
transform: { id: :src_id, name: :src_name },
|
111
|
+
transform_collection: Array,
|
112
|
+
transform_class: Hash,
|
113
|
+
extract_attribute: :[],
|
114
|
+
apply_attribute: :[]=,
|
115
|
+
store_transformed_object: :<<
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
let(:test_stream) { [{src_id: 42, src_name: "Alice"}, {src_id: 43, src_name: "Bob"} ] }
|
120
|
+
let(:extractions) { { test_stream: mock("extraction", name: "test_stream", extract: test_stream )}}
|
121
|
+
|
122
|
+
before do
|
123
|
+
TestTransform.stub!(:extractions).and_return(extractions)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should delegate to procs" do
|
127
|
+
transform.transform(test_stream).should == [
|
128
|
+
{id: 42, name: "Alice"},
|
129
|
+
{id: 43, name: "Bob"}
|
130
|
+
]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Migratrix do
|
4
|
+
describe "sanity check cat" do
|
5
|
+
it "is sanity checked" do
|
6
|
+
Migratrix.should_not be_nil
|
7
|
+
Migratrix.class.should == Module
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "convenience delegator methods" do
|
12
|
+
def spec_delegates_to_migratrix_class(method, *args)
|
13
|
+
if args.size > 0
|
14
|
+
Migratrix::Migratrix.should_receive(method).with(*args).once
|
15
|
+
else
|
16
|
+
Migratrix::Migratrix.should_receive(method).once
|
17
|
+
end
|
18
|
+
Migratrix.send(method, *args)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".logger" do
|
22
|
+
it "delegates to Migratrix::Migratrix" do
|
23
|
+
spec_delegates_to_migratrix_class :logger
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe ".logger=" do
|
28
|
+
let (:logger) { Logger.new(StringIO.new) }
|
29
|
+
it "delegates to Migratrix::Migratrix" do
|
30
|
+
spec_delegates_to_migratrix_class :logger=, logger
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".log_to" do
|
35
|
+
let (:buffer) { StringIO.new }
|
36
|
+
it "delegates to Migratrix::Migratrix" do
|
37
|
+
spec_delegates_to_migratrix_class :log_to, buffer
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".register_extraction" do
|
42
|
+
it "delegates to Migratrix::Migratrix" do
|
43
|
+
spec_delegates_to_migratrix_class :register_extraction, :marbles, Array, 3
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".extractions" do
|
48
|
+
it "delegates to Migratrix::Migratrix" do
|
49
|
+
spec_delegates_to_migratrix_class :extractions
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ".register_transform" do
|
54
|
+
it "delegates to Migratrix::Migratrix" do
|
55
|
+
spec_delegates_to_migratrix_class :register_transform, :marbles, Array, 3
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".transforms" do
|
60
|
+
it "delegates to Migratrix::Migratrix" do
|
61
|
+
spec_delegates_to_migratrix_class :transforms
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".register_load" do
|
66
|
+
it "delegates to Migratrix::Migratrix" do
|
67
|
+
spec_delegates_to_migratrix_class :register_load, :marbles, Array, 3
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe ".loads" do
|
72
|
+
it "delegates to Migratrix::Migratrix" do
|
73
|
+
spec_delegates_to_migratrix_class :loads
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "gem-installed components:" do
|
79
|
+
describe "extractions" do
|
80
|
+
it ":active_record is registered" do
|
81
|
+
Migratrix.extractions.class_for(:active_record).should == ::Migratrix::Extractions::ActiveRecord
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "transforms" do
|
86
|
+
it ":transform is registered" do
|
87
|
+
Migratrix.transforms.class_for(:transform).should == ::Migratrix::Transforms::Transform
|
88
|
+
end
|
89
|
+
|
90
|
+
it ":map is registered" do
|
91
|
+
Migratrix.transforms.class_for(:map).should == ::Migratrix::Transforms::Map
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# transforms: map, transform
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|