migratrix 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,9 +9,12 @@ module Migratrix
9
9
  require EXT + 'string_ext'
10
10
  require EXT + 'object_ext'
11
11
  require EXT + 'andand'
12
+ require APP + 'exceptions'
13
+
14
+ require APP + 'callbacks'
12
15
  require APP + 'loggable'
16
+ require APP + 'migration_strategy'
13
17
  require APP + 'valid_options'
14
- require APP + 'exceptions'
15
18
  require APP + 'registry'
16
19
  require APP + 'migration'
17
20
  require APP + 'migratrix'
@@ -0,0 +1,57 @@
1
+ require 'active_support/concern'
2
+
3
+ module Migratrix
4
+ # = Migratrix Callbacks
5
+ #
6
+ # Callbacks are hooks into the life cycle of a Migratrix Migration
7
+ # or Component object that allow you to trigger logic before or
8
+ # after an alteration of the object state. This can be used to do
9
+ # extra preparation or cleanup at each step along the way. Consider
10
+ # the <tt>Migration#migrate</tt> call:
11
+ #
12
+ # * (1) <tt>before_migrate</tt>
13
+ # * (2) <tt>before_extract</tt>
14
+ # * (-) <tt>extract</tt>
15
+ # * (3) <tt>after_extract</tt>
16
+ # * (4) <tt>before_transform</tt>
17
+ # * (-) <tt>transform</tt>
18
+ # * (5) <tt>after_transform</tt>
19
+ # * (6) <tt>before_load</tt>
20
+ # * (-) <tt>load</tt>
21
+ # * (7) <tt>after_load</tt>
22
+ # * (8) <tt>after_migrate</tt>
23
+ #
24
+ module Callbacks
25
+ extend ActiveSupport::Concern
26
+
27
+ CALLBACKS = [ :after_extract, :after_load, :after_migrate,
28
+ :after_transform, :around_extract, :around_load,
29
+ :around_migrate, :around_transform, :before_extract,
30
+ :before_load, :before_migrate, :before_transform
31
+ ]
32
+
33
+ included do
34
+ extend ActiveModel::Callbacks
35
+ # include ActiveModel::Validations::Callbacks
36
+
37
+ define_model_callbacks :migrate, :extract, :load, :transform
38
+ end
39
+
40
+ def migrate #:nodoc:
41
+ run_callbacks(:migrate) { super }
42
+ end
43
+
44
+ def extract #:nodoc:
45
+ run_callbacks(:extract) { super }
46
+ end
47
+
48
+ def transform(*) #:nodoc:
49
+ run_callbacks(:transform) { super }
50
+ end
51
+
52
+ def load(*) #:nodoc:
53
+ run_callbacks(:load) { super }
54
+ end
55
+ end
56
+ end
57
+
@@ -4,9 +4,11 @@ module Migratrix
4
4
  # Superclass for all migrations. Migratrix COULD check to see that a
5
5
  # loaded migration inherits from this class, but hey, duck typing.
6
6
  class Migration
7
- include ::Migratrix::Loggable
7
+ include Migratrix::Loggable
8
8
  include ActiveModel::AttributeMethods
9
9
  include Migratrix::ValidOptions
10
+ include Migratrix::MigrationStrategy
11
+ include Migratrix::Callbacks
10
12
 
11
13
  attr_accessor :options
12
14
  set_valid_options :console
@@ -101,54 +103,6 @@ module Migratrix
101
103
  def loads
102
104
  self.class.loads
103
105
  end
104
-
105
- def extract
106
- extracted_items = {}
107
- extractions.each do |name, extraction|
108
- extracted_items[name] = extraction.extract(options)
109
- end
110
- extracted_items
111
- end
112
-
113
- # Transforms source data into outputs. @transformed_items is a
114
- # hash of name => transformed_items.
115
- #
116
- def transform(extracted_items)
117
- transformed_items = { }
118
- transforms.each do |name, transform|
119
- transformed_items[transform.name] = transform.transform extracted_items[transform.extraction]
120
- end
121
- transformed_items
122
- end
123
-
124
- # Saves the migrated data by "loading" it into our database or
125
- # other data sink. Loaders have their own names, and by default
126
- # they depend on a transformed_items key of the same name, but you
127
- # may override this behavior by setting :source => :name or
128
- # possibly :source => [:name1, :name2, etc].
129
- def load(transformed_items)
130
- loaded_items = { }
131
- loads.each do |name, load|
132
- loaded_items[load.name] = load.load transformed_items[load.transform]
133
- end
134
- loaded_items
135
- end
136
-
137
- # Perform the migration
138
- # TODO: turn this into a strategy object. This pattern migrates
139
- # everything in all one go, while the user may want to do a batch
140
- # strategy. YAGNI: Rails 3 lets us defer the querying until we get
141
- # to the transform step, and then it's batched for us under the
142
- # hood. ...assuming, of course, we change the ActiveRecord
143
- # extraction's execute_extract method to return source instead of
144
- # all, but now the
145
- def migrate
146
- # This fn || @var API lets you write a method and either set the
147
- # @var or return the value.
148
- @extracted_items = extract || @extracted_items
149
- @transformed_items = transform(@extracted_items) || @transformed_items
150
- load @transformed_items
151
- end
152
106
  end
153
107
  end
154
108
 
@@ -0,0 +1,53 @@
1
+ module Migratrix
2
+ # TODO: blatant asymmetry here: extraction.extract gets options, but
3
+ # transform and load do not--and they should.
4
+ #
5
+ # = MigrationStrategy
6
+ #
7
+ # This module defines the basic strategy for a generic migration:
8
+ # extract gets a collection of items, transform transforms each
9
+ # item, then load calls save on that final transformed object.
10
+ module MigrationStrategy
11
+ def extract
12
+ extracted_items = {}
13
+ extractions.each do |name, extraction|
14
+ extracted_items[name] = extraction.extract(options)
15
+ end
16
+ extracted_items
17
+ end
18
+
19
+ # Transforms source data into outputs. @transformed_items is a
20
+ # hash of name => transformed_items.
21
+ #
22
+ def transform(extracted_items)
23
+ transformed_items = { }
24
+ transforms.each do |name, transform|
25
+ transformed_items[transform.name] = transform.transform extracted_items[transform.extraction]
26
+ end
27
+ transformed_items
28
+ end
29
+
30
+ # Saves the migrated data by "loading" it into our database or
31
+ # other data sink. Loaders have their own names, and by default
32
+ # they depend on a transformed_items key of the same name, but you
33
+ # may override this behavior by setting :source => :name or
34
+ # possibly :source => [:name1, :name2, etc].
35
+ def load(transformed_items)
36
+ loaded_items = { }
37
+ loads.each do |name, load|
38
+ loaded_items[load.name] = load.load transformed_items[load.transform]
39
+ end
40
+ loaded_items
41
+ end
42
+
43
+ # Perform the migration
44
+ def migrate
45
+ # This fn || @var API lets you write a method and either set the
46
+ # @var or return the value.
47
+ @extracted_items = extract || @extracted_items
48
+ @transformed_items = transform(@extracted_items) || @transformed_items
49
+ load @transformed_items
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,218 @@
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
+
23
+
24
+ class TestCallbackMigration < Migratrix::Migration
25
+ set_extraction :test, :no_op
26
+ set_transform :test, :no_op
27
+ set_load :test, :no_op
28
+ end
29
+
30
+ class MethodCallbackMigration < TestCallbackMigration
31
+ extend_extraction :test, {}
32
+ extend_transform :test, {}
33
+ extend_load :test, {}
34
+
35
+ attr_reader :before_migrate_called, :after_migrate_called, :around_migrate_called
36
+ attr_reader :before_extract_called, :after_extract_called, :around_extract_called
37
+ attr_reader :before_transform_called, :after_transform_called, :around_transform_called
38
+ attr_reader :before_load_called, :after_load_called, :around_load_called
39
+
40
+ before_migrate :before_migrate_method
41
+ after_migrate :after_migrate_method
42
+ around_migrate :around_migrate_method
43
+
44
+ def before_migrate_method
45
+ @before_migrate_called = true
46
+ end
47
+
48
+ def after_migrate_method
49
+ @after_migrate_called = true
50
+ end
51
+
52
+ def around_migrate_method
53
+ yield
54
+ @around_migrate_called = true
55
+ end
56
+
57
+ before_extract :before_extract_method
58
+ after_extract :after_extract_method
59
+ around_extract :around_extract_method
60
+
61
+ def before_extract_method
62
+ @before_extract_called = true
63
+ end
64
+
65
+ def after_extract_method
66
+ @after_extract_called = true
67
+ end
68
+
69
+ def around_extract_method
70
+ yield
71
+ @around_extract_called = true
72
+ end
73
+
74
+ before_transform :before_transform_method
75
+ after_transform :after_transform_method
76
+ around_transform :around_transform_method
77
+
78
+ def before_transform_method
79
+ @before_transform_called = true
80
+ end
81
+
82
+ def after_transform_method
83
+ @after_transform_called = true
84
+ end
85
+
86
+ def around_transform_method
87
+ yield
88
+ @around_transform_called = true
89
+ end
90
+
91
+ before_load :before_load_method
92
+ after_load :after_load_method
93
+ around_load :around_load_method
94
+
95
+ def before_load_method
96
+ @before_load_called = true
97
+ end
98
+
99
+ def after_load_method
100
+ @after_load_called = true
101
+ end
102
+
103
+ def around_load_method
104
+ yield
105
+ @around_load_called = true
106
+ end
107
+ end
108
+
109
+ class BlockCallbackMigration < TestCallbackMigration
110
+ attr_reader :before_migrate_called, :after_migrate_called
111
+ attr_reader :before_extract_called, :after_extract_called
112
+ attr_reader :before_transform_called, :after_transform_called
113
+ attr_reader :before_load_called, :after_load_called
114
+
115
+ before_migrate do
116
+ @before_migrate_called = true
117
+ end
118
+
119
+ after_migrate do
120
+ @after_migrate_called = true
121
+ end
122
+
123
+ before_extract do
124
+ @before_extract_called = true
125
+ end
126
+
127
+ after_extract do
128
+ @after_extract_called = true
129
+ end
130
+
131
+ before_transform do
132
+ @before_transform_called = true
133
+ end
134
+
135
+ after_transform do
136
+ @after_transform_called = true
137
+ end
138
+
139
+ before_load do
140
+ @before_load_called = true
141
+ end
142
+
143
+ after_load do
144
+ @after_load_called = true
145
+ end
146
+ end
147
+
148
+ describe "callbacks" do
149
+ describe "sanity check cat" do
150
+ it "is sanity checked" do
151
+ NoOpExtraction.should_not be_nil
152
+ NoOpTransform.should_not be_nil
153
+ NoOpLoad.should_not be_nil
154
+ TestCallbackMigration.should_not be_nil
155
+ MethodCallbackMigration.should_not be_nil
156
+ end
157
+ end
158
+
159
+ describe "with named callback methods" do
160
+ let(:migration) { MethodCallbackMigration.new }
161
+ before do
162
+ migration.migrate
163
+ end
164
+
165
+ it "calls migrate callbacks" do
166
+ migration.before_migrate_called.should be_true
167
+ migration.after_migrate_called.should be_true
168
+ migration.around_migrate_called.should be_true
169
+ end
170
+
171
+ it "calls extract callbacks" do
172
+ migration.before_extract_called.should be_true
173
+ migration.after_extract_called.should be_true
174
+ migration.around_extract_called.should be_true
175
+ end
176
+
177
+ it "calls transform callbacks" do
178
+ migration.before_transform_called.should be_true
179
+ migration.after_transform_called.should be_true
180
+ migration.around_transform_called.should be_true
181
+ end
182
+
183
+ it "calls load callbacks" do
184
+ migration.before_load_called.should be_true
185
+ migration.after_load_called.should be_true
186
+ migration.around_load_called.should be_true
187
+ end
188
+ end
189
+
190
+ describe "with block callbacks" do
191
+ let(:migration) { BlockCallbackMigration.new }
192
+ before do
193
+ migration.migrate
194
+ end
195
+
196
+ it "calls migrate callbacks" do
197
+ migration.before_migrate_called.should be_true
198
+ migration.after_migrate_called.should be_true
199
+ end
200
+
201
+ it "calls extract callbacks" do
202
+ migration.before_extract_called.should be_true
203
+ migration.after_extract_called.should be_true
204
+ end
205
+
206
+ it "calls transform callbacks" do
207
+ migration.before_transform_called.should be_true
208
+ migration.after_transform_called.should be_true
209
+ end
210
+
211
+ it "calls load callbacks" do
212
+ migration.before_load_called.should be_true
213
+ migration.after_load_called.should be_true
214
+ end
215
+ end
216
+ end
217
+
218
+
@@ -108,6 +108,5 @@ describe Migratrix::Migratrix do
108
108
  end
109
109
  end
110
110
  end
111
-
112
111
  end
113
112
 
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.1
4
+ version: 0.8.2
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-24 00:00:00.000000000Z
12
+ date: 2011-10-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: trollop
16
- requirement: &2164512960 !ruby/object:Gem::Requirement
16
+ requirement: &2152828360 !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: *2164512960
24
+ version_requirements: *2152828360
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
@@ -37,6 +37,7 @@ files:
37
37
  - bin/migratrix
38
38
  - lib/migratrix.rb
39
39
  - lib/migratrix/active_record_migration_helpers.rb
40
+ - lib/migratrix/callbacks.rb
40
41
  - lib/migratrix/exceptions.rb
41
42
  - lib/migratrix/extractions/active_record.rb
42
43
  - lib/migratrix/extractions/extraction.rb
@@ -44,6 +45,7 @@ files:
44
45
  - lib/migratrix/loads/yaml.rb
45
46
  - lib/migratrix/loggable.rb
46
47
  - lib/migratrix/migration.rb
48
+ - lib/migratrix/migration_strategy.rb
47
49
  - lib/migratrix/migratrix.rb
48
50
  - lib/migratrix/registry.rb
49
51
  - lib/migratrix/transforms/map.rb
@@ -54,6 +56,7 @@ files:
54
56
  - lib/patches/string_ext.rb
55
57
  - spec/fixtures/migrations/marbles_migration.rb
56
58
  - spec/lib/migratrix/_loggable_spec.rb
59
+ - spec/lib/migratrix/callbacks_spec.rb
57
60
  - spec/lib/migratrix/extractions/active_record_spec.rb
58
61
  - spec/lib/migratrix/extractions/extraction_spec.rb
59
62
  - spec/lib/migratrix/loads/load_spec.rb