migration_revert 1.0.0 → 1.1.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.
- data/README.md +39 -5
- data/lib/migration_revert/ext/command_recorder.rb +19 -14
- data/lib/migration_revert/ext/migration.rb +42 -2
- data/lib/migration_revert/version.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -6,14 +6,20 @@ Some commands are not reversible, for example the removal of a table or a column
|
|
6
6
|
|
7
7
|
Also, one downside is that it is now more difficult to write the reverse of a migration if `change` is used. When `up` and `down` were used, one could simply swap the code around.
|
8
8
|
|
9
|
-
|
9
|
+
This gem introduces `Migration#revert` that makes it trivial to revert a past migration, in part or in whole, or do the doing a reversible removal of a table/column.
|
10
10
|
|
11
11
|
Note that `revert` can even be called from legacy migrations using `up` & `down` and that it can revert legacy-style migrations too. For anyone changing their mind every second day, `revert` is fully nestable.
|
12
12
|
|
13
|
-
|
13
|
+
Sounds useful? Give a +1 to https://github.com/rails/rails/pull/7627
|
14
|
+
|
15
|
+
Also introduces `Migration#reversible` for data operations that can be reverted.
|
16
|
+
|
17
|
+
Sounds useful also? Give a +1 to https://github.com/rails/rails/pull/8177
|
14
18
|
|
15
19
|
## Usage
|
16
20
|
|
21
|
+
### revert
|
22
|
+
|
17
23
|
Reverses the migration commands for the given block and
|
18
24
|
the given migrations.
|
19
25
|
|
@@ -21,8 +27,6 @@ The following migration will remove the table 'horses'
|
|
21
27
|
and create the table 'apples' on the way up, and the reverse
|
22
28
|
on the way down.
|
23
29
|
|
24
|
-
This command can be nested.
|
25
|
-
|
26
30
|
class FixTLMigration < ActiveRecord::Migration
|
27
31
|
def change
|
28
32
|
revert do
|
@@ -37,7 +41,7 @@ This command can be nested.
|
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
40
|
-
Or equivalently, if
|
44
|
+
Or equivalently, if `TenderloveMigration` is defined as in the
|
41
45
|
documentation for Migration:
|
42
46
|
|
43
47
|
class FixupTLMigration < ActiveRecord::Migration
|
@@ -50,6 +54,36 @@ documentation for Migration:
|
|
50
54
|
end
|
51
55
|
end
|
52
56
|
|
57
|
+
This command can be nested.
|
58
|
+
|
59
|
+
### reversible
|
60
|
+
|
61
|
+
Used to specify an operation that can be run in one direction or another.
|
62
|
+
Call the methods +up+ and +down+ of the yielded object to run a block
|
63
|
+
only in one given direction.
|
64
|
+
The whole block will be called in the right order within the migration.
|
65
|
+
|
66
|
+
In the following example, the looping on users will always be done
|
67
|
+
when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
68
|
+
even when migrating down:
|
69
|
+
|
70
|
+
class SplitNameMigration < ActiveRecord::Migration
|
71
|
+
def change
|
72
|
+
add_column :users, :first_name, :string
|
73
|
+
add_column :users, :last_name, :string
|
74
|
+
|
75
|
+
reversible do |dir|
|
76
|
+
User.reset_column_information
|
77
|
+
User.all.each do |u|
|
78
|
+
dir.up { u.first_name, u.last_name = u.full_name.split(' ') }
|
79
|
+
dir.down { u.full_name = "#{u.first_name} #{u.last_name}" }
|
80
|
+
u.save
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
revert { add_column :users, :full_name, :string }
|
85
|
+
end
|
86
|
+
end
|
53
87
|
|
54
88
|
## Installation
|
55
89
|
|
@@ -18,13 +18,26 @@ module ActiveRecord
|
|
18
18
|
#
|
19
19
|
def record(*command, &block)
|
20
20
|
if @reverting
|
21
|
-
@commands << inverse_of(*command)
|
21
|
+
@commands << inverse_of(*command, &block)
|
22
22
|
else
|
23
23
|
@commands << (command << block)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
# Returns the inverse of the given command
|
28
|
+
#
|
29
|
+
# recorder.inverse_of(:rename_table, [:old, :new])
|
30
|
+
# # => [:rename_table, [:new, :old]]
|
31
|
+
#
|
32
|
+
# This method will raise an +IrreversibleMigration+ exception if it cannot
|
33
|
+
# invert the +commands+.
|
34
|
+
def inverse_of(command, args, &block)
|
35
|
+
method = :"invert_#{command}"
|
36
|
+
raise IrreversibleMigration unless respond_to?(method, true)
|
37
|
+
send(method, args, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
[:create_table, :create_join_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default, :add_reference, :remove_reference, :transaction].each do |method|
|
28
41
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
29
42
|
def #{method}(*args, &block) # def create_table(*args, &block)
|
30
43
|
record(:"#{method}", args, &block) # record(:create_table, args, &block)
|
@@ -34,18 +47,10 @@ module ActiveRecord
|
|
34
47
|
alias :add_belongs_to :add_reference
|
35
48
|
alias :remove_belongs_to :remove_reference
|
36
49
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
# This method will raise an +IrreversibleMigration+ exception if it cannot
|
43
|
-
# invert the +commands+.
|
44
|
-
#
|
45
|
-
def inverse_of(name, args)
|
46
|
-
method = :"invert_#{name}"
|
47
|
-
raise IrreversibleMigration unless respond_to?(method, true)
|
48
|
-
send(method, args)
|
50
|
+
private
|
51
|
+
|
52
|
+
def invert_transaction(args, &block)
|
53
|
+
[:transaction, args, block]
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
@@ -7,8 +7,6 @@ module ActiveRecord
|
|
7
7
|
# and create the table 'apples' on the way up, and the reverse
|
8
8
|
# on the way down.
|
9
9
|
#
|
10
|
-
# This command can be nested.
|
11
|
-
#
|
12
10
|
# class FixTLMigration < ActiveRecord::Migration
|
13
11
|
# def change
|
14
12
|
# revert do
|
@@ -36,6 +34,8 @@ module ActiveRecord
|
|
36
34
|
# end
|
37
35
|
# end
|
38
36
|
#
|
37
|
+
# This command can be nested.
|
38
|
+
#
|
39
39
|
def revert(*migration_classes)
|
40
40
|
run(*migration_classes.reverse, :revert => true) unless migration_classes.empty?
|
41
41
|
if block_given?
|
@@ -59,6 +59,46 @@ module ActiveRecord
|
|
59
59
|
@connection.respond_to?(:reverting) && @connection.reverting
|
60
60
|
end
|
61
61
|
|
62
|
+
class ReversibleBlockHelper < Struct.new(:reverting)
|
63
|
+
def up
|
64
|
+
yield unless reverting
|
65
|
+
end
|
66
|
+
|
67
|
+
def down
|
68
|
+
yield if reverting
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Used to specify an operation that can be run in one direction or another.
|
73
|
+
# Call the methods +up+ and +down+ of the yielded object to run a block
|
74
|
+
# only in one given direction.
|
75
|
+
# The whole block will be called in the right order within the migration.
|
76
|
+
# In the following example, the looping on users will always be done
|
77
|
+
# when the three columns 'first_name', 'last_name' and 'full_name' exist,
|
78
|
+
# even when migrating down:
|
79
|
+
#
|
80
|
+
# class SplitName < ActiveRecord::Migration
|
81
|
+
# def change
|
82
|
+
# add_column :users, :first_name, :string
|
83
|
+
# add_column :users, :last_name, :string
|
84
|
+
#
|
85
|
+
# reversible do |dir|
|
86
|
+
# User.reset_column_information
|
87
|
+
# User.all.each do |u|
|
88
|
+
# dir.up { u.first_name, u.last_name = u.full_name.split(' ') }
|
89
|
+
# dir.down { u.full_name = "#{u.first_name} #{u.last_name}" }
|
90
|
+
# u.save
|
91
|
+
# end
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# revert { add_column :users, :full_name, :string }
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
def reversible
|
98
|
+
helper = ReversibleBlockHelper.new(reverting?)
|
99
|
+
transaction{ yield helper }
|
100
|
+
end
|
101
|
+
|
62
102
|
# Runs the given migration classes.
|
63
103
|
# Last argument can specify options:
|
64
104
|
# - :direction (default is :up)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: migration_revert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|