migrator 1.0.0

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.
Binary file
@@ -0,0 +1,29 @@
1
+ # -*- ruby -*-
2
+
3
+ module Autotest::GnomeNotify
4
+
5
+ # Time notification will be displayed before disappearing automatically
6
+ EXPIRATION_IN_SECONDS = 2
7
+ ERROR_STOCK_ICON = "gtk-dialog-error"
8
+ SUCCESS_STOCK_ICON = "gtk-dialog-info"
9
+
10
+ # Convenience method to send an error notification message
11
+ #
12
+ # [stock_icon] Stock icon name of icon to display
13
+ # [title] Notification message title
14
+ # [message] Core message for the notification
15
+ def self.notify stock_icon, title, message
16
+ options = "-t #{EXPIRATION_IN_SECONDS * 1000} -i #{stock_icon}"
17
+ system "notify-send #{options} '#{title}' '#{message}'"
18
+ end
19
+
20
+ Autotest.add_hook :red do |at|
21
+ notify ERROR_STOCK_ICON, "Tests failed", "#{at.files_to_test.size} tests failed"
22
+ end
23
+
24
+ Autotest.add_hook :green do |at|
25
+ notify SUCCESS_STOCK_ICON, "All tests passed, good job!", ""
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,5 @@
1
+ === 1.0.0 / 2009-09-17
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
@@ -0,0 +1,13 @@
1
+ lib/aef/migrator/adapter.rb
2
+ lib/aef/migrator/migrator.rb
3
+ lib/aef/migrator/abstract_adapter.rb
4
+ lib/aef/migrator.rb
5
+ Manifest.txt
6
+ History.txt
7
+ Rakefile
8
+ .autotest
9
+ spec/spec_helper.rb
10
+ spec/mock_adapter.rb
11
+ spec/spec.opts
12
+ spec/migrator_spec.rb
13
+ README.rdoc
@@ -0,0 +1,209 @@
1
+ = Migrator
2
+
3
+ * Project: https://rubyforge.org/projects/migrator/
4
+ * RDoc: http://migrator.rubyforge.org/
5
+ * Github: http://github.com/aef/migrator/
6
+
7
+ == DESCRIPTION:
8
+
9
+ Migrator is a Ruby library for building general purpose versioning systems in
10
+ the style of ActiveRecord's migrations.
11
+
12
+ == FEATURES/PROBLEMS:
13
+
14
+ * Completely written in Ruby
15
+ * Tested and fully working on:
16
+ * Ubuntu Linux 8.10 amd64/x86_64
17
+ * Ruby 1.8.7p72
18
+ * Ruby 1.9.1p129
19
+ * Debian GNU/Linux 4.0 x86
20
+ * Ruby 1.8.6
21
+ * On Windows XP x86
22
+ * Ruby 1.8.6
23
+
24
+ == SYNOPSIS:
25
+
26
+ Load the gem:
27
+
28
+ require 'aef/migrator'
29
+
30
+ Build an adapter:
31
+
32
+ class Adapter
33
+ include Aef::Migrator::Adapter
34
+
35
+ # version() has to reflect the current version. Also version=() must exist
36
+ # to set the current version
37
+ attr_accessor :version,
38
+
39
+ # versions() has to provide a list of all versions in correct order
40
+ attr_accessor :versions
41
+
42
+ def initialize
43
+ self.versions = %w{a b c d e}
44
+ self.version = 'c'
45
+ end
46
+
47
+ # process() has to do the work behind a migration in forward direction. Will
48
+ # be called multiple times for multistep migrations.
49
+ def process(target_version)
50
+ puts "Migrating from #{version} to #{target_version}"
51
+
52
+ self.version = target_version
53
+ end
54
+
55
+ # revert() has to do the work behind a migration in backward direction. Will
56
+ # be called multiple times for multistep migrations.
57
+ def revert(target_version)
58
+ puts "Unmigrating from #{version} to #{target_version}"
59
+
60
+ self.version = target_version
61
+ end
62
+ end
63
+
64
+ Notice that the module Aef::Migrator::Adapter and the class
65
+ Aef::Migrator::AbstractAdapter both provide the basic method definitions for an
66
+ adapter but no functionality. The advantage are better error messages when you
67
+ forget to implement something, but you don't have to use either, as
68
+ Aef::Migrator defines an adapter only by checking for required methods.
69
+
70
+ Now we setup the migrator:
71
+
72
+ migrator = Aef::Migrator.new(Adapter.new)
73
+
74
+ After that we can use the versioning backend provided by the adapter to do
75
+ migrations:
76
+
77
+ migrator.version
78
+ # => "c"
79
+
80
+ migrator.up
81
+ migrator.version
82
+ # => "d"
83
+
84
+ migrator.up.version
85
+ # => "e"
86
+
87
+ migrator.down('b')
88
+ migrator.version
89
+ # => "b"
90
+
91
+ migrator.migrate('e').version
92
+ # => "e"
93
+
94
+ When migrations cannot be done, exceptions of the baseclass Aef::Migrator::Error
95
+ are raised. If there is a problem with the Adapter the exceptions will be of
96
+ Aef::Migrator::AdapterError which is a subclass of Aef::Migrator::Error.
97
+ Exceptions informing about unmatched migration constraints are from the subclass
98
+ Aef::Migrator::MigrationError.
99
+
100
+ We can also check if a migration is possible before running it. This way we
101
+ don't have to deal with exceptions when a migration cannot be done.
102
+
103
+ migrator.migratable?('e')
104
+ # => false
105
+
106
+ migrator.upable?
107
+ # => false
108
+
109
+ migrator.downable?('c')
110
+ # => true
111
+
112
+ See the files in the spec subdirectory for further examples of usage.
113
+
114
+ == REQUIREMENTS:
115
+
116
+ * rubygems
117
+
118
+ === Additional for automated testing
119
+ * hoe (>= 2.3.2)
120
+ * rspec (>= 1.2.8)
121
+
122
+ == INSTALL:
123
+
124
+ On *nix systems you may need to prefix the command with sudo to get root
125
+ privileges.
126
+
127
+ === High security (recommended)
128
+
129
+ There is a high security installation option available through rubygems. It is
130
+ highly recommended over the normal installation, although it may be a bit less
131
+ comfortable. To use the installation method, you will need my public key, which
132
+ I use for cryptographic signatures on all my gems. You can find the public key
133
+ and more detailed verification information in the aef-certificates section of my
134
+ rubyforge project[https://rubyforge.org/frs/?group_id=7890&release_id=31749]
135
+
136
+ Add the key to your rubygems' trusted certificates by the following command:
137
+
138
+ gem cert --add aef.pem
139
+
140
+ Now you can install the gem while automatically verifying it's signature by the
141
+ following command:
142
+
143
+ gem install migrator --ignore-dependencies -P HighSecurity
144
+
145
+ Please notice that you may need other keys for dependent libraries, so you may
146
+ have to install dependencies manually.
147
+
148
+ === Normal (insecure)
149
+
150
+ gem install migrator
151
+
152
+ === Github (also insecure)
153
+
154
+ Alternatively you could install migrator from github which may be a bit more
155
+ up to date. The version may however not be as stable as the normal gem and there
156
+ is no way to install the gem securely. Therefore this is not recommended.
157
+
158
+ gem install aef-migrator --source http://gems.github.com
159
+
160
+ === Automated testing
161
+
162
+ You can test this package through rspec on your system. First find the path
163
+ where the gem was installed to:
164
+
165
+ gem which aef/migrator
166
+
167
+ Go into the root directory of the installed gem and run the following command
168
+ to start the test runner:
169
+
170
+ rake spec
171
+
172
+ If something goes wrong you should be noticed through failing examples.
173
+
174
+ == DEVELOPMENT:
175
+
176
+ This software is developed in the source code management system git hosted
177
+ at github.com. You can download the most recent sourcecode through the following
178
+ command:
179
+
180
+ git clone git://github.com/aef/migrator.git
181
+
182
+ Help on making this software better is always very appreciated. If you want your
183
+ changes to be included in the official release, please send me a patch through
184
+ the project's tracker[https://rubyforge.org/tracker/?group_id=7890] at
185
+ rubyforge.org. You can generate a patch-file by the following command:
186
+
187
+ git diff > patch.diff
188
+
189
+ Please make sure to write tests for your changes and notice that I can't promise
190
+ to include your changes before reviewing them.
191
+
192
+ == LICENSE:
193
+
194
+ Copyright 2009 Alexander E. Fischer <aef@raxys.net>
195
+
196
+ This file is part of Migrator.
197
+
198
+ Migrator is free software: you can redistribute it and/or modify
199
+ it under the terms of the GNU General Public License as published by
200
+ the Free Software Foundation, either version 3 of the License, or
201
+ (at your option) any later version.
202
+
203
+ This program is distributed in the hope that it will be useful,
204
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
205
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
206
+ GNU General Public License for more details.
207
+
208
+ You should have received a copy of the GNU General Public License
209
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.spec('migrator') do
7
+ developer('Alexander E. Fischer', 'aef@raxys.net')
8
+
9
+ self.rubyforge_name = 'migrator'
10
+ self.extra_dev_deps = {
11
+ 'rspec' => '>= 1.2.8'
12
+ }
13
+ self.url = 'https://rubyforge.org/projects/migrator/'
14
+ self.readme_file = 'README.rdoc'
15
+ self.extra_rdoc_files = %w{README.rdoc}
16
+ self.spec_extras = {
17
+ :rdoc_options => ['--main', 'README.rdoc', '--inline-source', '--line-numbers', '--title', 'Migrator']
18
+ }
19
+ self.rspec_options = ['--options', 'spec/spec.opts']
20
+ self.remote_rdoc_dir = ''
21
+ end
22
+
23
+ # vim: syntax=Ruby
@@ -0,0 +1,27 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # Namespace for projects of Alexander E. Fischer <aef@raxys.net>
19
+ #
20
+ # If you want to be able to simply type Example instead of Aef::Example to
21
+ # address classes in this namespace simply write the following before using the
22
+ # classes:
23
+ #
24
+ # include Aef
25
+ module Aef
26
+ autoload :Migrator, 'aef/migrator/migrator'
27
+ end
@@ -0,0 +1,26 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # This class implements the interface for an adapter required by Aef::Migrator
19
+ # and could be used as an abstract base class. See also: Adapter
20
+ class Aef::Migrator::AbstractAdapter
21
+ include Aef::Migrator::Adapter
22
+
23
+ def initialize
24
+ raise NotImplementedError, 'Abstract class' if self.class == Aef::Migrator::AbstractAdapter
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # This module implements the interface for an adapter required by Aef::Migrator.
19
+ # See also: AbstractAdapter.
20
+ module Aef::Migrator::Adapter
21
+ def process(target_version)
22
+ raise NotImplementedError, 'The process method needs to be implemented'
23
+ end
24
+
25
+ def revert(target_version)
26
+ raise NotImplementedError, 'The revert method needs to be implemented'
27
+ end
28
+
29
+ def version
30
+ raise NotImplementedError, 'The version method needs to be implemented'
31
+ end
32
+
33
+ def version=(versions)
34
+ raise NotImplementedError, 'The version= method needs to be implemented'
35
+ end
36
+
37
+ def versions
38
+ raise NotImplementedError, 'The versions method needs to be implemented'
39
+ end
40
+ end
@@ -0,0 +1,170 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ # Class for building general purpose versioning systems in the style of
19
+ # ActiveRecord's migrations. An adapter object is needed for any instance of
20
+ # this class to have any use. See Adapter and AbstractAdapter for the required
21
+ # interface.
22
+ class Aef::Migrator
23
+ VERSION = '1.0.0'
24
+
25
+ # Baseclass for all Migrator specific exceptions
26
+ class Error < RuntimeError; end
27
+
28
+ # Baseclass for exceptions describing adapter errors
29
+ class AdapterError < Error; end
30
+ class AdapterMissingError < AdapterError; end
31
+ class AdapterMethodMissingError < AdapterError; end
32
+ class CurrentVersionInvalidError < AdapterError; end
33
+
34
+ # Baseclass for exceptions describing errors while processing migrations
35
+ class MigrationError < Error; end
36
+ class AlreadyOnTopError < MigrationError; end
37
+ class AlreadyOnBottomError < MigrationError; end
38
+ class TargetVersionInvalidError < MigrationError; end
39
+ class UpMigrationInvalidError < MigrationError; end
40
+ class DownMigrationInvalidError < MigrationError; end
41
+ class MigrationUnneccessaryError < MigrationError; end
42
+
43
+ autoload :Adapter, 'aef/migrator/adapter'
44
+ autoload :AbstractAdapter, 'aef/migrator/abstract_adapter'
45
+
46
+ attr_accessor :adapter
47
+
48
+ def initialize(adapter)
49
+ @adapter = adapter
50
+ end
51
+
52
+ # Checks if a migration is possible
53
+ def migratable?(target_version, direction = nil)
54
+ !!migration_steps(target_version, direction)
55
+ rescue MigrationError
56
+ false
57
+ end
58
+
59
+ # Checks if an up migration is possible
60
+ def upable?(target_version = nil)
61
+ migratable?(target_version, :up)
62
+ end
63
+
64
+ # Checks if a down migration is possible
65
+ def downable?(target_version = nil)
66
+ migratable?(target_version, :down)
67
+ end
68
+
69
+ # Process a migration
70
+ #
71
+ # Raises MigratorError in case of invalid actions
72
+ def migrate(target_version, direction = nil)
73
+ params = migration_steps(target_version, direction)
74
+
75
+ params[:steps].each do |version|
76
+ @adapter.send(params[:action], version)
77
+ end
78
+
79
+ self
80
+ end
81
+
82
+ # Process an up migration
83
+ #
84
+ # Raises MigratorError in case of invalid actions
85
+ def up(target_version = nil)
86
+ migrate(target_version, :up)
87
+ end
88
+
89
+ # Process a down migration
90
+ #
91
+ # Raises MigratorError in case of invalid actions
92
+ def down(target_version = nil)
93
+ migrate(target_version, :down)
94
+ end
95
+
96
+ # Current version
97
+ def version
98
+ @adapter.version
99
+ end
100
+
101
+ # All possible versions in correct order
102
+ def versions
103
+ @adapter.versions
104
+ end
105
+
106
+ protected
107
+
108
+ # Returns a hash with an :action value and a :steps array with all versions
109
+ # to reach the target
110
+ def migration_steps(target_version, direction)
111
+ raise ArgumentError, 'Invalid direction' unless [nil, :up, :down].include?(direction)
112
+
113
+ unless @adapter
114
+ raise AdapterMissingError, 'No adapter set'
115
+ else
116
+ Adapter.instance_methods(false).each do |method|
117
+ raise AdapterMethodMissingError, "Adapter must respond to #{method}" unless @adapter.respond_to?(method)
118
+ end
119
+ end
120
+
121
+ version_list = versions
122
+ current_version = version
123
+
124
+ indices = {:current => version_list.index(current_version)}
125
+
126
+ raise CurrentVersionInvalidError, "Current version not in version list: " +
127
+ "'#{current_version}'" unless indices[:current]
128
+
129
+ # When direction is set and target_version is unset step up/down by one
130
+ unless target_version
131
+ case direction
132
+ when :up
133
+ step_up = indices[:current] + 1
134
+ raise AlreadyOnTopError, 'Already on highest version' unless step_up < version_list.size
135
+ indices[:target] = step_up
136
+ target_version = version_list[step_up]
137
+ when :down
138
+ step_down = indices[:current] - 1
139
+ raise AlreadyOnBottomError, 'Already on lowest version' unless step_down >= 0
140
+ indices[:target] = step_down
141
+ target_version = version_list[step_down]
142
+ else
143
+ raise ArgumentError, 'No target version specified'
144
+ end
145
+ else
146
+ indices[:target] = version_list.index(target_version)
147
+
148
+ raise TargetVersionInvalidError, 'Target version not in version list: ' +
149
+ "'#{target_version}'" unless indices[:target]
150
+ end
151
+
152
+ if indices[:current] < indices[:target]
153
+ raise DownMigrationInvalidError, "Current version '#{current_version}' " +
154
+ "is lower than '#{target_version}'" if direction == :down
155
+
156
+ indices[:current] += 1
157
+
158
+ {:action => :process, :steps => version_list[indices.values.min..indices.values.max]}
159
+ elsif indices[:current] > indices[:target]
160
+ raise UpMigrationInvalidError, "Current version '#{current_version}' " +
161
+ "is higher than '#{target_version}'" if direction == :up
162
+
163
+ indices[:current] -= 1
164
+
165
+ {:action => :revert, :steps => version_list[indices.values.min..indices.values.max].reverse}
166
+ else
167
+ raise MigrationUnneccessaryError, "Current version equals target version: '#{current_version}'"
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,214 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'spec/spec_helper'
19
+
20
+ describe Aef::Migrator do
21
+ before(:all) do
22
+ class BrokenAdapter < described_class::AbstractAdapter
23
+ undef :process
24
+ end
25
+ end
26
+
27
+ before(:each) do
28
+ @adapter = MockAdapter.new
29
+ @adapter.verbose = false
30
+ @migrator = described_class.new(@adapter)
31
+ end
32
+
33
+ it "should complain about invalid direction params" do
34
+ lambda {
35
+ @migrator.migrate('a', :invalid)
36
+ }.should raise_error(ArgumentError)
37
+ end
38
+
39
+ it "should complain when no adapter is set" do
40
+ lambda {
41
+ @migrator.adapter = nil
42
+ @migrator.migrate('a')
43
+ }.should raise_error(described_class::AdapterMissingError)
44
+ end
45
+
46
+ it "should complain about missing adapter methods" do
47
+ lambda {
48
+ @migrator.adapter = BrokenAdapter.new
49
+ @migrator.migrate('a')
50
+ }.should raise_error(described_class::AdapterMethodMissingError)
51
+ end
52
+
53
+ it "should complain about current versions which are not in versions" do
54
+ lambda {
55
+ @adapter.version = 'f'
56
+ @migrator.migrate('a')
57
+ }.should raise_error(described_class::CurrentVersionInvalidError)
58
+ end
59
+
60
+ it "should complain about target versions which are not in versions" do
61
+ lambda {
62
+ @migrator.migrate('invalid')
63
+ }.should raise_error(described_class::TargetVersionInvalidError)
64
+ end
65
+
66
+ it "should complain about migrating to the current version" do
67
+ lambda {
68
+ @migrator.migrate('c')
69
+ }.should raise_error(described_class::MigrationUnneccessaryError)
70
+ end
71
+
72
+ it "should be able to implicitly migrate one version up" do
73
+ lambda {
74
+ @migrator.up
75
+ }.should change{@migrator.version}.from('c').to('d')
76
+ end
77
+
78
+ it "should be able to implicitly migrate one version down" do
79
+ lambda {
80
+ @migrator.down
81
+ }.should change{@migrator.version}.from('c').to('b')
82
+ end
83
+
84
+ it "should be able to explicitly migrate one version up" do
85
+ lambda {
86
+ @migrator.up('d')
87
+ }.should change{@migrator.version}.from('c').to('d')
88
+ end
89
+
90
+ it "should be able to explicitly migrate one version down" do
91
+ lambda {
92
+ @migrator.down('b')
93
+ }.should change{@migrator.version}.from('c').to('b')
94
+ end
95
+
96
+ it "should be able to migrate multiple version up with one call" do
97
+ lambda {
98
+ @migrator.up('e')
99
+ }.should change{@migrator.version}.from('c').to('e')
100
+ end
101
+
102
+ it "should be able to migrate multiple version down with one call" do
103
+ lambda {
104
+ @migrator.down('a')
105
+ }.should change{@migrator.version}.from('c').to('a')
106
+ end
107
+
108
+ it "should prohibit migration in wrong direction when up method is used" do
109
+ lambda {
110
+ @migrator.up('a')
111
+ }.should raise_error(described_class::UpMigrationInvalidError)
112
+ end
113
+
114
+ it "should prohibit migration in wrong direction when down method is used" do
115
+ lambda {
116
+ @migrator.down('e')
117
+ }.should raise_error(described_class::DownMigrationInvalidError)
118
+ end
119
+
120
+ it "should allow up migration with generic migrate method" do
121
+ lambda {
122
+ @migrator.migrate('e')
123
+ }.should change{@migrator.version}.from('c').to('e')
124
+ end
125
+
126
+ it "should allow down migration with generic migrate method" do
127
+ lambda {
128
+ @migrator.migrate('a')
129
+ }.should change{@migrator.version}.from('c').to('a')
130
+ end
131
+
132
+ it "should complain about invalid direction params when migratable? is called" do
133
+ lambda {
134
+ @migrator.migratable?('a', :invalid)
135
+ }.should raise_error(ArgumentError)
136
+ end
137
+
138
+ it "should complain when no adapter is set when migratable? is called" do
139
+ lambda {
140
+ @migrator.adapter = nil
141
+ @migrator.migrate('a')
142
+ }.should raise_error(described_class::AdapterMissingError)
143
+ end
144
+
145
+ it "should complain about missing adapter methods when migratable? is called" do
146
+ lambda {
147
+ @migrator.adapter = BrokenAdapter.new
148
+ @migrator.migratable?('a')
149
+ }.should raise_error(described_class::AdapterMethodMissingError)
150
+ end
151
+
152
+ it "should complain about current versions which are not in versions when migratable? is called" do
153
+ lambda {
154
+ @adapter.version = 'f'
155
+ @migrator.migratable?('a')
156
+ }.should raise_error(described_class::CurrentVersionInvalidError)
157
+ end
158
+
159
+ it "should indicate that a migration to an invalid target version is impossible" do
160
+ @migrator.migratable?('invalid').should be_false
161
+ end
162
+
163
+ it "should indicate that implicitly migrating one version up is possible" do
164
+ @migrator.upable?.should be_true
165
+ end
166
+
167
+ it "should indicate that implicitly migrating one version down is possible" do
168
+ @migrator.downable?.should be_true
169
+ end
170
+
171
+ it "should indicate that migrating one version up is possible" do
172
+ @migrator.upable?('d').should be_true
173
+ end
174
+
175
+ it "should indicate that migrating one version down is possible" do
176
+ @migrator.downable?('b').should be_true
177
+ end
178
+
179
+ it "should indicate that a multi-step migration up is possible" do
180
+ @migrator.upable?('e').should be_true
181
+ end
182
+
183
+ it "should indicate that a multi-step migration down is possible" do
184
+ @migrator.downable?('a').should be_true
185
+ end
186
+
187
+ it "should indicate a wrong direction migration is impossible when upable? method is used" do
188
+ @migrator.upable?('a').should be_false
189
+ end
190
+
191
+ it "should indicate a wrong direction migration is impossible when downable? method is used" do
192
+ @migrator.downable?('e').should be_false
193
+ end
194
+
195
+ it "should indicate that up migration is possible when migratable? method is used" do
196
+ @migrator.migratable?('e').should be_true
197
+ end
198
+
199
+ it "should indicate that down migration is possible when migratable? method is used" do
200
+ @migrator.migratable?('a').should be_true
201
+ end
202
+
203
+ it "should return itself for method changing through method migrate" do
204
+ @migrator.migrate('d').should eql(@migrator)
205
+ end
206
+
207
+ it "should return itself for method changing through method up" do
208
+ @migrator.up.should eql(@migrator)
209
+ end
210
+
211
+ it "should return itself for method changing through method down" do
212
+ @migrator.down.should eql(@migrator)
213
+ end
214
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ class MockAdapter < Aef::Migrator::AbstractAdapter
19
+ attr_accessor :version, :versions_hash, :verbose
20
+
21
+ def initialize
22
+ @versions_hash = {
23
+ 'a' => 'a.version',
24
+ 'b' => 'b.version',
25
+ 'c' => 'c.version',
26
+ 'd' => 'd.version',
27
+ 'e' => 'e.version'
28
+ }
29
+ self.version = 'c'
30
+ end
31
+
32
+ def process(target_version)
33
+ puts "Migrating from #{version} to #{target_version} (#{versions_hash[target_version]})" if @verbose
34
+
35
+ self.version = target_version
36
+ end
37
+
38
+ def revert(target_version)
39
+ puts "Unmigrating from #{version} to #{target_version} (#{versions_hash[version]})" if @verbose
40
+
41
+ self.version = target_version
42
+ end
43
+
44
+ def versions
45
+ versions_hash.keys.sort
46
+ end
47
+ end
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,25 @@
1
+ # Copyright 2009 Alexander E. Fischer <aef@raxys.net>
2
+ #
3
+ # This file is part of Migrator.
4
+ #
5
+ # Migrator is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ $LOAD_PATH.unshift('lib')
19
+
20
+ require 'aef/migrator'
21
+ require 'spec/mock_adapter'
22
+
23
+ Spec::Runner.configure do |config|
24
+
25
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: migrator
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander E. Fischer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDKDCCAhCgAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQwwCgYDVQQDDANhZWYx
14
+ FTATBgoJkiaJk/IsZAEZFgVyYXh5czETMBEGCgmSJomT8ixkARkWA25ldDAeFw0w
15
+ OTAyMjUyMDM5MDhaFw0xMDAyMjUyMDM5MDhaMDoxDDAKBgNVBAMMA2FlZjEVMBMG
16
+ CgmSJomT8ixkARkWBXJheHlzMRMwEQYKCZImiZPyLGQBGRYDbmV0MIIBIjANBgkq
17
+ hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoYtj0qad5/MpbdttITzBH0h1SNe6eO7R
18
+ 7qVeqNYu6qDQAQ0rYc0JhubJCWYrZEJorHEBhUFU6cdQgQOs78wiJaDgkeU7YfXB
19
+ q2l125kJ8aHkA1ukrK2/DRzp2AHEmzxHIYpXV5/63h+NWjCP+uKvTELYsotS2MKt
20
+ 3d43E0QajsPZu2ZuNFwkroqeue872gMHUldGOVy5WtSd9ajw2xI/CociY6746dL+
21
+ pYriV3QaYtR/ezeaLpKBLsc5T1UQ07t7Xs7mI281tdmRvpLdP5dQhjzInfio0CJv
22
+ 1Pf5bZUjGG0K9RW2Gb/tGPSYEETiLMubjH61OwBooXKiWR5cs4/1BQIDAQABozkw
23
+ NzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUSYvjhG2EWnR5kx5l
24
+ DAewXCkJOVEwDQYJKoZIhvcNAQEFBQADggEBAB2ryDbU4bQtnunKv/AXq4CuO3LS
25
+ kik9Xhye8E/5dTcsgitCZJXAqx0rHcK0u2EHnjA5CDcdF5JB7XgSvRrQkFWoW/9K
26
+ lCB4ih+sB2AI2IUiYBeoCGctXdBQ020prqop/oTQEudzFk/gyQ686lp06HdLRt+O
27
+ HoQjTIab8vmfgIubjPdIRzokMfHbelvhLi+mQfWVghRhs2jpEfdXbL0w5nNw+trp
28
+ rO70Dw59hduDUOpgpxew+PLbs4vP1tb1QKPG+39C+PZtosbbf1fai0hqYV1txMCx
29
+ 55akF+N8NbO6tpVDy6TMagqa10LfEpiQH6dvDHe/xdAqYOCrXKpmqzwu2PI=
30
+ -----END CERTIFICATE-----
31
+
32
+ date: 2009-09-17 00:00:00 +02:00
33
+ default_executable:
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: rspec
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.8
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: hoe
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.3.2
54
+ version:
55
+ description: |-
56
+ Migrator is a Ruby library for building general purpose versioning systems in
57
+ the style of ActiveRecord's migrations.
58
+ email:
59
+ - aef@raxys.net
60
+ executables: []
61
+
62
+ extensions: []
63
+
64
+ extra_rdoc_files:
65
+ - Manifest.txt
66
+ - History.txt
67
+ - README.rdoc
68
+ files:
69
+ - lib/aef/migrator/adapter.rb
70
+ - lib/aef/migrator/migrator.rb
71
+ - lib/aef/migrator/abstract_adapter.rb
72
+ - lib/aef/migrator.rb
73
+ - Manifest.txt
74
+ - History.txt
75
+ - Rakefile
76
+ - .autotest
77
+ - spec/spec_helper.rb
78
+ - spec/mock_adapter.rb
79
+ - spec/spec.opts
80
+ - spec/migrator_spec.rb
81
+ - README.rdoc
82
+ has_rdoc: true
83
+ homepage: https://rubyforge.org/projects/migrator/
84
+ licenses: []
85
+
86
+ post_install_message:
87
+ rdoc_options:
88
+ - --main
89
+ - README.rdoc
90
+ - --inline-source
91
+ - --line-numbers
92
+ - --title
93
+ - Migrator
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: "0"
107
+ version:
108
+ requirements: []
109
+
110
+ rubyforge_project: migrator
111
+ rubygems_version: 1.3.5
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Migrator is a Ruby library for building general purpose versioning systems in the style of ActiveRecord's migrations.
115
+ test_files: []
116
+
Binary file