migratrix 0.8.2 → 0.8.3

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.
@@ -45,19 +45,40 @@ module Migratrix
45
45
  # TODO: THIS IS HUGE DUPLICATION, REFACTOR REFACTOR REFACTOR
46
46
 
47
47
  # extraction crap
48
- def self.set_extraction(extraction_name, class_name, options={})
49
- extractions[extraction_name] = Migratrix.extraction(class_name, extraction_name, options)
48
+ # set_extraction :nickname, :registered_name, options_hash
49
+ # set_extraction :nickname, :registered_name # options = {}
50
+ # set_extraction :registered_name, options_hash # nickname = :default
51
+ # set_extraction :registered_name # nickname = :default, options={}
52
+ def self.set_extraction(nickname, registered_name=nil, options=nil)
53
+ # barf, seriously these args need some detangler.
54
+ if registered_name.nil?
55
+ nickname, registered_name, options = :default, nickname, {}
56
+ elsif options.nil?
57
+ if registered_name.is_a?(Hash)
58
+ nickname, registered_name, options = :default, nickname, registered_name
59
+ else
60
+ nickname, registered_name, options = nickname, registered_name, {}
61
+ end
62
+ end
63
+ extractions[nickname] = Migratrix.extraction(nickname, registered_name, options)
50
64
  end
51
65
 
52
- def self.extend_extraction(extraction_name, options={})
53
- migration = ancestors.detect {|k| k.respond_to?(:extractions) && k.extractions[extraction_name]}
54
- raise ExtractionNotDefined.new("Could not extend extractar '%s'; no parent Migration defines it" % extraction_name) unless migration
55
- extraction = migration.extractions[extraction_name]
56
- extractions[extraction_name] = extraction.class.new(extraction_name, extraction.options.merge(options))
66
+ def self.extend_extraction(nickname, options={})
67
+ migration = ancestors.detect {|k| k.respond_to?(:extractions) && k.extractions[nickname]}
68
+ raise ExtractionNotDefined.new("Could not extend extraction '%s'; no parent Migration defines it" % nickname) unless migration
69
+ extraction = migration.extractions[nickname]
70
+ extractions[nickname] = extraction.class.new(nickname, extraction.options.merge(options))
57
71
  end
58
72
 
59
73
  def self.extractions
60
74
  @extractions ||= {}
75
+ ancestry = ancestors.select {|klass| klass != self && klass.respond_to?(:extractions) }.reverse
76
+ # take oldest ancestor and merge extractions forward
77
+ ext = {}
78
+ ancestry.each do |ancestor|
79
+ ext = ext.merge(ancestor.extractions || {})
80
+ end
81
+ @extractions = ext.merge(@extractions)
61
82
  end
62
83
 
63
84
  def extractions
@@ -65,8 +86,22 @@ module Migratrix
65
86
  end
66
87
 
67
88
  # transform crap
68
- def self.set_transform(name, type, options={})
69
- transforms[name] = Migratrix.transform(name, type, options)
89
+ # set_transform :nickname, :registered_name, options_hash
90
+ # set_transform :nickname, :registered_name # options = {}
91
+ # set_transform :registered_name, options_hash # nickname = :default
92
+ # set_transform :registered_name # nickname = :default, options={}
93
+ def self.set_transform(nickname, registered_name=nil, options=nil)
94
+ # barf, seriously these args need some detangler.
95
+ if registered_name.nil?
96
+ nickname, registered_name, options = :default, nickname, {}
97
+ elsif options.nil?
98
+ if registered_name.is_a?(Hash)
99
+ nickname, registered_name, options = :default, nickname, registered_name
100
+ else
101
+ nickname, registered_name, options = nickname, registered_name, {}
102
+ end
103
+ end
104
+ transforms[nickname] = Migratrix.transform(nickname, registered_name, options)
70
105
  end
71
106
 
72
107
  def self.extend_transform(transform_name, options={})
@@ -78,6 +113,13 @@ module Migratrix
78
113
 
79
114
  def self.transforms
80
115
  @transforms ||= {}
116
+ ancestry = ancestors.select {|klass| klass != self && klass.respond_to?(:transforms) }.reverse
117
+ # take oldest ancestor and merge transforms forward
118
+ ext = {}
119
+ ancestry.each do |ancestor|
120
+ ext = ext.merge(ancestor.transforms || {})
121
+ end
122
+ @transforms = ext.merge(@transforms)
81
123
  end
82
124
 
83
125
  def transforms
@@ -85,10 +127,28 @@ module Migratrix
85
127
  end
86
128
 
87
129
  # load crap
88
- def self.set_load(name, type, options={})
89
- loads[name] = Migratrix.load(name, type, options)
130
+ # set_load :nickname, :registered_name, options_hash
131
+ # set_load :nickname, :registered_name # options = {}
132
+ # set_load :registered_name, options_hash # nickname = :default
133
+ # set_load :registered_name # nickname = :default, options={}
134
+ def self.set_load(nickname, registered_name=nil, options=nil)
135
+ # barf, seriously these args need some detangler.
136
+ if registered_name.nil?
137
+ nickname, registered_name, options = :default, nickname, {}
138
+ elsif options.nil?
139
+ if registered_name.is_a?(Hash)
140
+ nickname, registered_name, options = :default, nickname, registered_name
141
+ else
142
+ nickname, registered_name, options = nickname, registered_name, {}
143
+ end
144
+ end
145
+ loads[nickname] = Migratrix.load(nickname, registered_name, options)
90
146
  end
91
147
 
148
+ # def self.set_load(name, type, options={})
149
+ # loads[name] = Migratrix.load(name, type, options)
150
+ # end
151
+
92
152
  def self.extend_load(load_name, options={})
93
153
  migration = ancestors.detect {|k| k.respond_to?(:loads) && k.loads[load_name]}
94
154
  raise LoadNotDefined.new("Could not extend extractar '%s'; no parent Migration defines it" % load_name) unless migration
@@ -98,6 +158,13 @@ module Migratrix
98
158
 
99
159
  def self.loads
100
160
  @loads ||= {}
161
+ ancestry = ancestors.select {|klass| klass != self && klass.respond_to?(:loads) }.reverse
162
+ # take oldest ancestor and merge loads forward
163
+ ext = {}
164
+ ancestry.each do |ancestor|
165
+ ext = ext.merge(ancestor.loads || {})
166
+ end
167
+ @loads = ext.merge(@loads)
101
168
  end
102
169
 
103
170
  def loads
@@ -52,12 +52,12 @@ module Migratrix
52
52
  registry[:extractions]
53
53
  end
54
54
 
55
- def self.register_extraction(class_name, klass, options={})
56
- self.extractions.register(class_name, klass, options)
55
+ def self.register_extraction(registered_name, klass, options={})
56
+ self.extractions.register(registered_name, klass, options)
57
57
  end
58
58
 
59
- def self.extraction(class_name, extraction_name, options={})
60
- self.extractions.class_for(class_name).new(extraction_name, options)
59
+ def self.extraction(nickname, registered_name, options={})
60
+ self.extractions.class_for(registered_name).new(nickname, options)
61
61
  end
62
62
  # --------------------
63
63
 
@@ -71,8 +71,8 @@ module Migratrix
71
71
  self.transforms.register(name, klass, options)
72
72
  end
73
73
 
74
- def self.transform(transform_name, class_name, options={})
75
- self.transforms.class_for(class_name).new(transform_name, options)
74
+ def self.transform(nickname, registered_name, options={})
75
+ self.transforms.class_for(registered_name).new(nickname, options)
76
76
  end
77
77
  # --------------------
78
78
 
@@ -86,8 +86,8 @@ module Migratrix
86
86
  self.loads.register(name, klass, options)
87
87
  end
88
88
 
89
- def self.load(load_name, class_name, options={})
90
- self.loads.class_for(class_name).new(load_name, options)
89
+ def self.load(nickname, registered_name, options={})
90
+ self.loads.class_for(registered_name).new(nickname, options)
91
91
  end
92
92
  # --------------------
93
93
 
@@ -0,0 +1,22 @@
1
+ class NoOpExtraction < Migratrix::Extractions::Extraction
2
+ def extract(options={})
3
+ []
4
+ end
5
+ end
6
+
7
+ class NoOpTransform < Migratrix::Transforms::Transform
8
+ def transform(exts, options={})
9
+ []
10
+ end
11
+ end
12
+
13
+ class NoOpLoad < Migratrix::Loads::Load
14
+ def load(trans, options={})
15
+ []
16
+ end
17
+ end
18
+
19
+ Migratrix::Migratrix.register_extraction :no_op, NoOpExtraction
20
+ Migratrix::Migratrix.register_transform :no_op, NoOpTransform
21
+ Migratrix::Migratrix.register_load :no_op, NoOpLoad
22
+
@@ -0,0 +1,11 @@
1
+ require 'test_migration'
2
+
3
+ class ChildMigration1 < TestMigration
4
+ end
5
+
6
+ class ChildMigration2 < TestMigration
7
+ end
8
+
9
+ class GrandchildMigration1 < ChildMigration1
10
+ end
11
+
@@ -0,0 +1,3 @@
1
+ class TestMigration < Migratrix::Migration
2
+ end
3
+
@@ -1,25 +1,4 @@
1
- class NoOpExtraction < Migratrix::Extractions::Extraction
2
- def extract(options={})
3
- []
4
- end
5
- end
6
-
7
- class NoOpTransform < Migratrix::Transforms::Transform
8
- def transform(exts, options={})
9
- []
10
- end
11
- end
12
-
13
- class NoOpLoad < Migratrix::Loads::Load
14
- def load(trans, options={})
15
- []
16
- end
17
- end
18
-
19
- Migratrix::Migratrix.register_extraction :no_op, NoOpExtraction
20
- Migratrix::Migratrix.register_transform :no_op, NoOpTransform
21
- Migratrix::Migratrix.register_load :no_op, NoOpLoad
22
-
1
+ require 'no_op_components'
23
2
 
24
3
  class TestCallbackMigration < Migratrix::Migration
25
4
  set_extraction :test, :no_op
@@ -1,18 +1,7 @@
1
1
  require 'spec_helper'
2
-
3
- # This migration is embedded in migration_spec.rb to allow testing of
4
- # the class methods that specialize subclasses.
5
- class TestMigration < Migratrix::Migration
6
- end
7
-
8
- class ChildMigration1 < TestMigration
9
- end
10
-
11
- class ChildMigration2 < TestMigration
12
- end
13
-
14
- class GrandchildMigration1 < ChildMigration1
15
- end
2
+ require 'no_op_components'
3
+ require 'test_migration'
4
+ require 'inherited_migrations'
16
5
 
17
6
  describe Migratrix::Migration do
18
7
  let(:migration) { TestMigration.new :cheese => 42 }
@@ -30,6 +19,31 @@ describe Migratrix::Migration do
30
19
  end
31
20
  end
32
21
 
22
+ [:extraction, :transform, :load].each do |component|
23
+ describe ".set_#{component}" do
24
+ describe "without options" do
25
+ it "creates #{component} with empty options" do
26
+ Migratrix::Migratrix.should_receive(component).with(:test, :no_op, {})
27
+ TestMigration.send "set_#{component}", :test, :no_op
28
+ end
29
+ end
30
+
31
+ describe "without nickname" do
32
+ it "creates #{component} with nickname :default" do
33
+ Migratrix::Migratrix.should_receive(component).with(:default, :no_op, {opt: 2})
34
+ TestMigration.send "set_#{component}", :no_op, {opt: 2}
35
+ end
36
+ end
37
+
38
+ describe "without options or nickname" do
39
+ it "creates #{component} with nickname :default and empty options hash" do
40
+ Migratrix::Migratrix.should_receive(component).with(:default, :no_op, {})
41
+ TestMigration.send "set_#{component}", :no_op
42
+ end
43
+ end
44
+ end
45
+ end
46
+
33
47
  describe "with mocked components" do
34
48
  let(:map) { { :id => :id, :name => :name }}
35
49
  let(:extraction) {
@@ -162,7 +176,7 @@ describe Migratrix::Migration do
162
176
  end
163
177
  end
164
178
 
165
- describe "extending" do
179
+ describe "with inheritance" do
166
180
  before do
167
181
  [TestMigration, ChildMigration1, ChildMigration2, GrandchildMigration1].each do |klass|
168
182
  [:extractions, :transforms, :loads].each do |kollection|
@@ -172,56 +186,68 @@ describe Migratrix::Migration do
172
186
  TestMigration.set_extraction :cheese, :extraction, { first_option: 'id>100' }
173
187
  TestMigration.set_transform :cheese, :transform, { first_option: 'id>100' }
174
188
  TestMigration.set_load :cheese, :load, { first_option: 'id>100' }
175
-
176
189
  end
177
190
 
178
- [:extraction, :transform, :load ].each do |component|
179
- describe "#{component}" do
180
- it "extends the #{component} to child class" do
181
- ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2 })
182
- ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>100'}
183
- end
184
-
185
- it "extends the #{component} to the grandchild class" do
186
- ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2 })
187
- GrandchildMigration1.send("extend_#{component}", :cheese, { surprise_option: 50 })
188
- GrandchildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>100', surprise_option: 50 }
189
- end
190
-
191
- it "extends the #{component} to the grandchild class even if the child class does not extend" do
192
- GrandchildMigration1.send("extend_#{component}", :cheese, { surprise_option: 50 })
193
- GrandchildMigration1.new.send("#{component}s")[:cheese].options.should == { first_option: 'id>100', surprise_option: 50 }
191
+ describe "extending" do
192
+ [:extraction, :transform, :load ].each do |component|
193
+ describe "#{component}" do
194
+ it "extends the #{component} to child class" do
195
+ ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2 })
196
+ ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>100'}
197
+ end
198
+
199
+ it "extends the #{component} to the grandchild class" do
200
+ ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2 })
201
+ GrandchildMigration1.send("extend_#{component}", :cheese, { surprise_option: 50 })
202
+ GrandchildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>100', surprise_option: 50 }
203
+ end
204
+
205
+ it "extends the #{component} to the grandchild class even if the child class does not extend" do
206
+ GrandchildMigration1.send("extend_#{component}", :cheese, { surprise_option: 50 })
207
+ GrandchildMigration1.new.send("#{component}s")[:cheese].options.should == { first_option: 'id>100', surprise_option: 50 }
208
+ end
209
+
210
+ it "overrides parent options" do
211
+ ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
212
+ ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
213
+ end
214
+
215
+ it "does not affect sibling class options" do
216
+ ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
217
+ ChildMigration2.send("extend_#{component}", :cheese, { zany_option: Hash, first_option: 'id>75' })
218
+ ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
219
+ ChildMigration2.new.send("#{component}s")[:cheese].options.should == { zany_option: Hash, first_option: 'id>75'}
220
+ end
221
+
222
+ it "does not affect parent class options" do
223
+ ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
224
+ ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
225
+ TestMigration.new.send("#{component}s")[:cheese].options.should == { first_option: 'id>100'}
226
+ end
227
+
228
+ it "raises #{component.capitalize}NotDefined if no parent has that #{component}" do
229
+ exception = "Migratrix::#{component.capitalize}NotDefined".constantize
230
+ lambda { ChildMigration1.send("extend_#{component}", :blargle, { second_option: 2, first_option: 'id>50' }) }.should raise_error(exception)
231
+ end
194
232
  end
233
+ end
234
+ end
195
235
 
196
- it "overrides parent options" do
197
- ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
198
- ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
199
- end
236
+ [:extraction, :transform, :load].each do |component|
237
+ describe "#{component}s" do
238
+ let(:opts) { { opts_option: 'id>100' } }
200
239
 
201
- it "does not affect sibling class options" do
202
- ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
203
- ChildMigration2.send("extend_#{component}", :cheese, { zany_option: Hash, first_option: 'id>75' })
204
- ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
205
- ChildMigration2.new.send("#{component}s")[:cheese].options.should == { zany_option: Hash, first_option: 'id>75'}
240
+ it "inherit from ancestor #{component}s" do
241
+ GrandchildMigration1.send("#{component}s").should == TestMigration.send("#{component}s")
206
242
  end
207
243
 
208
- it "does not affect parent class options" do
209
- ChildMigration1.send("extend_#{component}", :cheese, { second_option: 2, first_option: 'id>50' })
210
- ChildMigration1.new.send("#{component}s")[:cheese].options.should == { second_option: 2, first_option: 'id>50'}
211
- TestMigration.new.send("#{component}s")[:cheese].options.should == { first_option: 'id>100'}
212
- end
213
-
214
- it "raises #{component.capitalize}NotDefined if no parent has that #{component}" do
215
- exception = "Migratrix::#{component.capitalize}NotDefined".constantize
216
- lambda { ChildMigration1.send("extend_#{component}", :blargle, { second_option: 2, first_option: 'id>50' }) }.should raise_error(exception)
244
+ it "are merged with ancestor #{component}s" do
245
+ GrandchildMigration1.send "set_#{component}", :wine, component, opts
246
+ my_component = GrandchildMigration1.send("#{component}s")[:wine]
247
+ GrandchildMigration1.send("#{component}s").should == TestMigration.send("#{component}s").merge( { wine: my_component })
217
248
  end
218
249
  end
219
250
  end
220
-
221
-
222
- # TODO: lambdas cannot be deep-copied, and form closures at the
223
- # time of creation. Is there a way to detect if a lambda has a
224
- # closure?
225
251
  end
226
252
  end
227
253
 
@@ -77,7 +77,7 @@ describe Migratrix::Migratrix do
77
77
  end
78
78
 
79
79
  describe "with logger as a singleton" do
80
- let (:migration) { Migratrix::MarblesMigration.new }
80
+ let (:migration) { Migratrix::Migration.new }
81
81
  let (:buffer) { StringIO.new }
82
82
 
83
83
  def spec_all_loggers_are(this_logger)
@@ -85,7 +85,7 @@ describe Migratrix::Migratrix do
85
85
  Migratrix::Migratrix.logger.should == this_logger
86
86
  migratrix.logger.should == this_logger
87
87
  migration.logger.should == this_logger
88
- Migratrix::MarblesMigration.logger.should == this_logger
88
+ Migratrix::Migration.logger.should == this_logger
89
89
  end
90
90
 
91
91
  describe ".logger=" do
data/spec/spec_helper.rb CHANGED
@@ -28,7 +28,9 @@ Dir[SPEC + "support/**/*.rb"].each {|f| require f}
28
28
 
29
29
  require LIB + 'migratrix'
30
30
 
31
- require SPEC + "fixtures/migrations/marbles_migration"
31
+ $:.unshift SPEC + "fixtures/migrations/"
32
+ $:.unshift SPEC + "fixtures/components/"
33
+
32
34
 
33
35
  # Redirect singleton logger to logger of our choice, then release it
34
36
  # after the spec finishes or crashes.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: migratrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-25 00:00:00.000000000Z
12
+ date: 2011-10-26 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: trollop
16
- requirement: &2152828360 !ruby/object:Gem::Requirement
16
+ requirement: &2161676040 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2152828360
24
+ version_requirements: *2161676040
25
25
  description: Migratrix, a Rails legacy database migration tool supporting multiple
26
26
  strategies, including arbitrary n-ary migrations (1->n, n->1, n->m), arbitrary inputs
27
27
  and outputs (ActiveRecord, bare SQL, CSV) and migration logging
@@ -54,7 +54,9 @@ files:
54
54
  - lib/patches/andand.rb
55
55
  - lib/patches/object_ext.rb
56
56
  - lib/patches/string_ext.rb
57
- - spec/fixtures/migrations/marbles_migration.rb
57
+ - spec/fixtures/components/no_op_components.rb
58
+ - spec/fixtures/migrations/inherited_migrations.rb
59
+ - spec/fixtures/migrations/test_migration.rb
58
60
  - spec/lib/migratrix/_loggable_spec.rb
59
61
  - spec/lib/migratrix/callbacks_spec.rb
60
62
  - spec/lib/migratrix/extractions/active_record_spec.rb
@@ -1,19 +0,0 @@
1
- module Migratrix
2
- # Fake migration fixture for "Marbles"
3
- class MarblesMigration < Migration
4
- # :nocov: # because we play some games with file loading/unloading, SimpleCov often misses lines in this file
5
- def initialize(options={})
6
- super
7
- @migrated = false
8
- end
9
-
10
- def migrate
11
- @migrated = true
12
- end
13
-
14
- def migrated?
15
- @migrated
16
- end
17
- # :nocov:
18
- end
19
- end