dm-migrations 0.9.2 → 0.9.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.
- data/History.txt +1 -0
- data/Manifest.txt +38 -0
- data/{README → README.txt} +1 -2
- data/Rakefile +22 -29
- data/db/migrations/1_create_people_table.rb +12 -0
- data/db/migrations/2_add_dob_to_people.rb +13 -0
- data/db/migrations/config.rb +4 -0
- data/examples/sample_migration.rb +61 -0
- data/examples/sample_migration_spec.rb +46 -0
- data/lib/dm-migrations/version.rb +5 -0
- data/lib/migration.rb +10 -12
- data/lib/sql.rb +3 -103
- data/lib/sql/postgresql.rb +10 -10
- data/lib/sql/sqlite3.rb +1 -8
- data/lib/sql/table_creator.rb +55 -0
- data/lib/sql/table_modifier.rb +53 -0
- data/spec/integration/migration_runner_spec.rb +58 -55
- data/spec/integration/migration_spec.rb +99 -99
- data/spec/integration/sql_spec.rb +118 -108
- data/spec/spec.opts +2 -1
- data/spec/spec_helper.rb +4 -11
- data/spec/unit/migration_spec.rb +447 -0
- data/spec/unit/sql/column_spec.rb +18 -0
- data/spec/unit/sql/postgresql_spec.rb +99 -0
- data/spec/unit/sql/sqlite3_extensions_spec.rb +109 -0
- data/spec/unit/sql/table_creator_spec.rb +93 -0
- data/spec/unit/sql/table_modifier_spec.rb +52 -0
- data/spec/unit/sql/table_spec.rb +31 -0
- data/spec/unit/sql_spec.rb +10 -0
- metadata +48 -17
@@ -1,148 +1,158 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
[:sqlite3, :mysql, :postgres].each do |adapter|
|
5
|
+
next unless eval("HAS_#{adapter.to_s.upcase}")
|
6
|
+
describe "Using Adapter #{adapter}, " do
|
7
|
+
describe DataMapper::Migration, "#create_table helper" do
|
8
|
+
before do
|
9
|
+
@creator = DataMapper::Migration::TableCreator.new(repository(adapter).adapter, :people) do
|
10
|
+
column :name, String
|
11
|
+
column :long_string, String, :size => 200
|
12
|
+
end
|
9
13
|
end
|
10
|
-
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
it "should have a #create_table helper" do
|
16
|
+
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) { }
|
17
|
+
@migration.should respond_to(:create_table)
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
it "should have a table_name" do
|
21
|
+
@creator.table_name.should == "people"
|
22
|
+
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
it "should have an adapter" do
|
25
|
+
@creator.instance_eval("@adapter").should == repository(adapter).adapter
|
26
|
+
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
it "should have an options hash" do
|
29
|
+
@creator.opts.should be_kind_of(Hash)
|
30
|
+
@creator.opts.should == {}
|
31
|
+
end
|
29
32
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
it "should have an array of columns" do
|
34
|
+
@creator.instance_eval("@columns").should be_kind_of(Array)
|
35
|
+
@creator.instance_eval("@columns").should have(2).items
|
36
|
+
@creator.instance_eval("@columns").first.should be_kind_of(DataMapper::Migration::TableCreator::Column)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should quote the table name for the adapter" do
|
40
|
+
@creator.quoted_table_name.should == (adapter == :mysql ? '`people`' : '"people"')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should allow for custom options" do
|
44
|
+
columns = @creator.instance_eval("@columns")
|
45
|
+
col = columns.detect{|c| c.name == "long_string"}
|
46
|
+
col.instance_eval("@type").should include("200")
|
47
|
+
end
|
35
48
|
|
36
|
-
it "should quote the table name for the adapter" do
|
37
|
-
@creator.quoted_table_name.should == '"people"'
|
38
49
|
end
|
39
50
|
|
40
|
-
|
51
|
+
describe DataMapper::Migration, "#modify_table helper" do
|
52
|
+
before do
|
53
|
+
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) { }
|
54
|
+
end
|
41
55
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
56
|
+
it "should have a #modify_table helper" do
|
57
|
+
@migration.should respond_to(:modify_table)
|
58
|
+
end
|
46
59
|
|
47
|
-
it "should have a #modify_table helper" do
|
48
|
-
@migration.should respond_to(:modify_table)
|
49
60
|
end
|
50
61
|
|
51
|
-
|
62
|
+
describe DataMapper::Migration, "other helpers" do
|
63
|
+
before do
|
64
|
+
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) { }
|
65
|
+
end
|
52
66
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
67
|
+
it "should have a #drop_table helper" do
|
68
|
+
@migration.should respond_to(:drop_table)
|
69
|
+
end
|
57
70
|
|
58
|
-
it "should have a #drop_table helper" do
|
59
|
-
@migration.should respond_to(:drop_table)
|
60
71
|
end
|
61
72
|
|
62
|
-
|
73
|
+
describe DataMapper::Migration, "version tracking" do
|
74
|
+
before do
|
75
|
+
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) do
|
76
|
+
up { :ran_up }
|
77
|
+
down { :ran_down }
|
78
|
+
end
|
63
79
|
|
64
|
-
|
65
|
-
before do
|
66
|
-
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) do
|
67
|
-
up { :ran_up }
|
68
|
-
down { :ran_down }
|
80
|
+
@migration.send(:create_migration_info_table_if_needed)
|
69
81
|
end
|
70
82
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
def insert_migration_record
|
75
|
-
DataMapper.repository.adapter.execute("INSERT INTO migration_info (migration_name) VALUES ('create_people_table')")
|
76
|
-
end
|
83
|
+
def insert_migration_record
|
84
|
+
DataMapper.repository.adapter.execute("INSERT INTO migration_info (migration_name) VALUES ('create_people_table')")
|
85
|
+
end
|
77
86
|
|
78
|
-
|
79
|
-
|
80
|
-
|
87
|
+
it "should know if the migration_info table exists" do
|
88
|
+
@migration.send(:migration_info_table_exists?).should be_true
|
89
|
+
end
|
81
90
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
91
|
+
it "should know if the migration_info table does not exist" do
|
92
|
+
repository.adapter.execute("DROP TABLE migration_info") rescue nil
|
93
|
+
@migration.send(:migration_info_table_exists?).should be_false
|
94
|
+
end
|
86
95
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
96
|
+
it "should be able to find the migration_info record for itself" do
|
97
|
+
insert_migration_record
|
98
|
+
@migration.send(:migration_record).should_not be_empty
|
99
|
+
end
|
91
100
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
101
|
+
it "should know if a migration needs_up?" do
|
102
|
+
@migration.send(:needs_up?).should be_true
|
103
|
+
insert_migration_record
|
104
|
+
@migration.send(:needs_up?).should be_false
|
105
|
+
end
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
107
|
+
it "should know if a migration needs_down?" do
|
108
|
+
@migration.send(:needs_down?).should be_false
|
109
|
+
insert_migration_record
|
110
|
+
@migration.send(:needs_down?).should be_true
|
111
|
+
end
|
103
112
|
|
104
|
-
|
105
|
-
|
106
|
-
|
113
|
+
it "should properly quote the migration_info table for use in queries" do
|
114
|
+
@migration.send(:migration_info_table).should == '"migration_info"'
|
115
|
+
end
|
107
116
|
|
108
|
-
|
109
|
-
|
110
|
-
|
117
|
+
it "should properly quote the migration_info.migration_name column for use in queries" do
|
118
|
+
@migration.send(:migration_name_column).should == '"migration_name"'
|
119
|
+
end
|
111
120
|
|
112
|
-
|
113
|
-
|
121
|
+
it "should properly quote the migration's name for use in queries"
|
122
|
+
# TODO how to i call the adapter's #escape_sql method?
|
114
123
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
124
|
+
it "should create the migration_info table if it doesn't exist" do
|
125
|
+
repository.adapter.execute("DROP TABLE migration_info")
|
126
|
+
@migration.send(:migration_info_table_exists?).should be_false
|
127
|
+
@migration.send(:create_migration_info_table_if_needed)
|
128
|
+
@migration.send(:migration_info_table_exists?).should be_true
|
129
|
+
end
|
121
130
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
131
|
+
it "should insert a record into the migration_info table on up" do
|
132
|
+
@migration.send(:migration_record).should be_empty
|
133
|
+
@migration.perform_up.should == :ran_up
|
134
|
+
@migration.send(:migration_record).should_not be_empty
|
135
|
+
end
|
127
136
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
137
|
+
it "should remove a record from the migration_info table on down" do
|
138
|
+
insert_migration_record
|
139
|
+
@migration.send(:migration_record).should_not be_empty
|
140
|
+
@migration.perform_down.should == :ran_down
|
141
|
+
@migration.send(:migration_record).should be_empty
|
142
|
+
end
|
134
143
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
144
|
+
it "should not run the up action if the record exists in the table" do
|
145
|
+
insert_migration_record
|
146
|
+
@migration.perform_up.should_not == :ran_up
|
147
|
+
end
|
139
148
|
|
140
|
-
|
141
|
-
|
142
|
-
|
149
|
+
it "should not run the down action if the record does not exist in the table" do
|
150
|
+
@migration.perform_down.should_not == :ran_down
|
151
|
+
end
|
143
152
|
|
144
|
-
|
145
|
-
|
153
|
+
after do
|
154
|
+
repository.adapter.execute("DELETE FROM migration_info") if @migration.send(:migration_info_table_exists?)
|
155
|
+
end
|
146
156
|
end
|
147
157
|
end
|
148
158
|
end
|
data/spec/spec.opts
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -5,24 +5,17 @@ require 'pathname'
|
|
5
5
|
require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-migrations'
|
6
6
|
require Pathname(__FILE__).dirname.parent.expand_path + 'lib/migration_runner'
|
7
7
|
|
8
|
-
#require 'fileutils'
|
9
|
-
|
10
|
-
#DB_FILE = "#{Dir.pwd}/migration_test.db"
|
11
|
-
#FileUtils.touch DB_FILE
|
12
|
-
|
13
|
-
#DataMapper.setup(:default, "sqlite3://#{DB_FILE}")
|
14
|
-
#DataMapper::Logger.new(nil, :debug)
|
15
|
-
|
16
8
|
def load_driver(name, default_uri)
|
17
|
-
return false if ENV['ADAPTER'] != name.to_s
|
9
|
+
#return false if ENV['ADAPTER'] != name.to_s
|
18
10
|
|
19
11
|
lib = "do_#{name}"
|
20
12
|
|
21
13
|
begin
|
22
|
-
gem lib, '=0.9.
|
14
|
+
gem lib, '=0.9.3'
|
23
15
|
require lib
|
24
|
-
DataMapper.setup(name,
|
16
|
+
DataMapper.setup(name, default_uri)
|
25
17
|
DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
|
18
|
+
puts "Loaded #{name}"
|
26
19
|
true
|
27
20
|
rescue Gem::LoadError => e
|
28
21
|
warn "Could not load #{lib}: #{e}"
|
@@ -0,0 +1,447 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname + '../spec_helper'
|
3
|
+
|
4
|
+
require Pathname(__FILE__).dirname + '../../lib/migration'
|
5
|
+
|
6
|
+
describe 'Migration' do
|
7
|
+
|
8
|
+
before do
|
9
|
+
@adapter = mock('adapter', :class => DataMapper::Adapters::Sqlite3Adapter)
|
10
|
+
@repo = mock('DataMapper.repository', :adapter => @adapter)
|
11
|
+
DataMapper.stub!(:repository).and_return(@repo)
|
12
|
+
@m = DataMapper::Migration.new(1, :do_nothing, {}) {}
|
13
|
+
@m.stub!(:write) # silence any output
|
14
|
+
end
|
15
|
+
|
16
|
+
[:position, :name, :database, :adapter].each do |meth|
|
17
|
+
it "should respond to ##{meth}" do
|
18
|
+
@m.should respond_to(meth)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'initialization' do
|
23
|
+
it 'should set @position from the given position' do
|
24
|
+
@m.instance_variable_get(:@position).should == 1
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should set @name from the given name' do
|
28
|
+
@m.instance_variable_get(:@name).should == :do_nothing
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set @options from the options hash' do
|
32
|
+
@m.instance_variable_get(:@options).should == {}
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should set @database from the default repository if no :database option is given' do
|
36
|
+
DataMapper.should_receive(:repository).with(:default).and_return(@repo)
|
37
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should set @database to the repository specified with the :database option' do
|
41
|
+
DataMapper.should_receive(:repository).with(:foobar).and_return(@repo)
|
42
|
+
DataMapper::Migration.new(1, :do_nothing, :database => :foobar) {}
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should determine the class of the adapter to be extended' do
|
46
|
+
@adapter.should_receive(:class).and_return(DataMapper::Adapters::Sqlite3Adapter)
|
47
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should extend the adapter with the right module' do
|
51
|
+
@adapter.should_receive(:extend).with(SQL::Sqlite3)
|
52
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should raise "Unsupported adapter" on an unknown adapter' do
|
56
|
+
@adapter.should_receive(:class).any_number_of_times.and_return("InvalidAdapter")
|
57
|
+
lambda {
|
58
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
59
|
+
}.should raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should set @verbose from the options hash' do
|
63
|
+
m = DataMapper::Migration.new(1, :do_nothing, :verbose => false) {}
|
64
|
+
m.instance_variable_get(:@verbose).should be_false
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should set @verbose to true by default' do
|
68
|
+
@m.instance_variable_get(:@verbose).should be_true
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should set the @up_action to an empty block' do
|
72
|
+
@m.instance_variable_get(:@up_action).should be_kind_of(Proc)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should set the @down_action to an empty block' do
|
76
|
+
@m.instance_variable_get(:@down_action).should be_kind_of(Proc)
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should evaluate the given block'
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should set the @up_action when #up is called with a block' do
|
84
|
+
action = lambda {}
|
85
|
+
@m.up(&action)
|
86
|
+
@m.instance_variable_get(:@up_action).should == action
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'should set the @up_action when #up is called with a block' do
|
90
|
+
action = lambda {}
|
91
|
+
@m.down(&action)
|
92
|
+
@m.instance_variable_get(:@down_action).should == action
|
93
|
+
end
|
94
|
+
|
95
|
+
describe 'perform_up' do
|
96
|
+
before do
|
97
|
+
@up_action = mock('proc', :call => true)
|
98
|
+
@m.instance_variable_set(:@up_action, @up_action)
|
99
|
+
@m.stub!(:needs_up?).and_return(true)
|
100
|
+
@m.stub!(:update_migration_info)
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should call the action assigned to @up_action and return the result' do
|
104
|
+
@up_action.should_receive(:call).and_return(:result)
|
105
|
+
@m.perform_up.should == :result
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should output a status message with the position and name of the migration' do
|
109
|
+
@m.should_receive(:write).with(/Performing Up Migration #1: do_nothing/)
|
110
|
+
@m.perform_up
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'should not run if it doesnt need to be' do
|
114
|
+
@m.should_receive(:needs_up?).and_return(false)
|
115
|
+
@up_action.should_not_receive(:call)
|
116
|
+
@m.perform_up
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'should update the migration info table' do
|
120
|
+
@m.should_receive(:update_migration_info).with(:up)
|
121
|
+
@m.perform_up
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should not update the migration info table if the migration does not need run' do
|
125
|
+
@m.should_receive(:needs_up?).and_return(false)
|
126
|
+
@m.should_not_receive(:update_migration_info)
|
127
|
+
@m.perform_up
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
describe 'perform_down' do
|
133
|
+
before do
|
134
|
+
@down_action = mock('proc', :call => true)
|
135
|
+
@m.instance_variable_set(:@down_action, @down_action)
|
136
|
+
@m.stub!(:needs_down?).and_return(true)
|
137
|
+
@m.stub!(:update_migration_info)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'should call the action assigned to @down_action and return the result' do
|
141
|
+
@down_action.should_receive(:call).and_return(:result)
|
142
|
+
@m.perform_down.should == :result
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'should output a status message with the position and name of the migration' do
|
146
|
+
@m.should_receive(:write).with(/Performing Down Migration #1: do_nothing/)
|
147
|
+
@m.perform_down
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'should not run if it doesnt need to be' do
|
151
|
+
@m.should_receive(:needs_down?).and_return(false)
|
152
|
+
@down_action.should_not_receive(:call)
|
153
|
+
@m.perform_down
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'should update the migration info table' do
|
157
|
+
@m.should_receive(:update_migration_info).with(:down)
|
158
|
+
@m.perform_down
|
159
|
+
end
|
160
|
+
|
161
|
+
it 'should not update the migration info table if the migration does not need run' do
|
162
|
+
@m.should_receive(:needs_down?).and_return(false)
|
163
|
+
@m.should_not_receive(:update_migration_info)
|
164
|
+
@m.perform_down
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
describe 'methods used in the action blocks' do
|
170
|
+
|
171
|
+
describe '#execute' do
|
172
|
+
before do
|
173
|
+
@adapter.stub!(:execute)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'should send the SQL it its executing to the adapter execute method' do
|
177
|
+
@adapter.should_receive(:execute).with('SELECT SOME SQL')
|
178
|
+
@m.execute('SELECT SOME SQL')
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should output the SQL it is executing' do
|
182
|
+
@m.should_receive(:write).with(/SELECT SOME SQL/)
|
183
|
+
@m.execute('SELECT SOME SQL')
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe 'helpers' do
|
188
|
+
before do
|
189
|
+
@m.stub!(:execute) # don't actually run anything
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#create_table' do
|
193
|
+
before do
|
194
|
+
@tc = mock('TableCreator', :to_sql => 'CREATE TABLE')
|
195
|
+
SQL::TableCreator.stub!(:new).and_return(@tc)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should create a new TableCreator object' do
|
199
|
+
SQL::TableCreator.should_receive(:new).with(@adapter, :users, {}).and_return(@tc)
|
200
|
+
@m.create_table(:users) { }
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should convert the TableCreator object to an sql statement' do
|
204
|
+
@tc.should_receive(:to_sql).and_return('CREATE TABLE')
|
205
|
+
@m.create_table(:users) { }
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should execute the create table sql' do
|
209
|
+
@m.should_receive(:execute).with('CREATE TABLE')
|
210
|
+
@m.create_table(:users) { }
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
describe '#drop_table' do
|
216
|
+
it 'should quote the table name' do
|
217
|
+
@adapter.should_receive(:quote_table_name).with('users')
|
218
|
+
@m.drop_table :users
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should execute the DROP TABLE sql for the table' do
|
222
|
+
@adapter.stub!(:quote_table_name).and_return("'users'")
|
223
|
+
@m.should_receive(:execute).with(%{DROP TABLE 'users'})
|
224
|
+
@m.drop_table :users
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
describe '#modify_table' do
|
230
|
+
before do
|
231
|
+
@tm = mock('TableModifier', :statements => [])
|
232
|
+
SQL::TableModifier.stub!(:new).and_return(@tm)
|
233
|
+
end
|
234
|
+
|
235
|
+
it 'should create a new TableModifier object' do
|
236
|
+
SQL::TableModifier.should_receive(:new).with(@adapter, :users, {}).and_return(@tm)
|
237
|
+
@m.modify_table(:users){ }
|
238
|
+
end
|
239
|
+
|
240
|
+
it 'should get the statements from the TableModifier object' do
|
241
|
+
@tm.should_receive(:statements).and_return([])
|
242
|
+
@m.modify_table(:users){ }
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'should iterate over the statements and execute each one' do
|
246
|
+
@tm.should_receive(:statements).and_return(['SELECT 1', 'SELECT 2'])
|
247
|
+
@m.should_receive(:execute).with('SELECT 1')
|
248
|
+
@m.should_receive(:execute).with('SELECT 2')
|
249
|
+
@m.modify_table(:users){ }
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
|
254
|
+
describe 'sorting' do
|
255
|
+
it 'should order things by position' do
|
256
|
+
m1 = DataMapper::Migration.new(1, :do_nothing){}
|
257
|
+
m2 = DataMapper::Migration.new(2, :do_nothing_else){}
|
258
|
+
|
259
|
+
(m1 <=> m2).should == -1
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should order things by name when they have the same position' do
|
263
|
+
m1 = DataMapper::Migration.new(1, :do_nothing_a){}
|
264
|
+
m2 = DataMapper::Migration.new(1, :do_nothing_b){}
|
265
|
+
|
266
|
+
(m1 <=> m2).should == -1
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
describe 'formatting output' do
|
272
|
+
describe '#say' do
|
273
|
+
it 'should output the message' do
|
274
|
+
@m.should_receive(:write).with(/Paul/)
|
275
|
+
@m.say("Paul")
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should indent the message with 4 spaces by default' do
|
279
|
+
@m.should_receive(:write).with(/^\s{4}/)
|
280
|
+
@m.say("Paul")
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'should indext the message with a given number of spaces' do
|
284
|
+
@m.should_receive(:write).with(/^\s{3}/)
|
285
|
+
@m.say("Paul", 3)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe '#say_with_time' do
|
290
|
+
before do
|
291
|
+
@m.stub!(:say)
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should say the message with an indent of 2' do
|
295
|
+
@m.should_receive(:say).with("Paul", 2)
|
296
|
+
@m.say_with_time("Paul"){}
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'should output the time it took' do
|
300
|
+
@m.should_receive(:say).with(/\d+/, 2)
|
301
|
+
@m.say_with_time("Paul"){}
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe '#write' do
|
306
|
+
before do
|
307
|
+
# need a new migration object, because the main one had #write stubbed to silence output
|
308
|
+
@m = DataMapper::Migration.new(1, :do_nothing) {}
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'should puts the message' do
|
312
|
+
@m.should_receive(:puts).with("Paul")
|
313
|
+
@m.write("Paul")
|
314
|
+
end
|
315
|
+
|
316
|
+
it 'should not puts the message if @verbose is false' do
|
317
|
+
@m.instance_variable_set(:@verbose, false)
|
318
|
+
@m.should_not_receive(:puts)
|
319
|
+
@m.write("Paul")
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
describe 'working with the migration_info table' do
|
327
|
+
before do
|
328
|
+
@adapter.stub!(:storage_exists?).and_return(true)
|
329
|
+
@adapter.stub!(:quote_table_name).and_return(%{'users'})
|
330
|
+
@adapter.stub!(:quote_column_name).and_return(%{'migration_name'})
|
331
|
+
end
|
332
|
+
|
333
|
+
describe '#update_migration_info' do
|
334
|
+
it 'should add a record of the migration' do
|
335
|
+
@m.should_receive(:execute).with(
|
336
|
+
%Q{INSERT INTO 'users' ('migration_name') VALUES ('do_nothing')}
|
337
|
+
)
|
338
|
+
@m.update_migration_info(:up)
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'should remove the record of the migration' do
|
342
|
+
@m.should_receive(:execute).with(
|
343
|
+
%Q{DELETE FROM 'users' WHERE 'migration_name' = 'do_nothing'}
|
344
|
+
)
|
345
|
+
@m.update_migration_info(:down)
|
346
|
+
end
|
347
|
+
|
348
|
+
it 'should try to create the migration_info table' do
|
349
|
+
@m.should_receive(:create_migration_info_table_if_needed)
|
350
|
+
@m.update_migration_info(:up)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
describe '#create_migration_info_table_if_needed' do
|
355
|
+
it 'should create the migration info table' do
|
356
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
357
|
+
@m.should_receive(:execute).with(
|
358
|
+
%Q{CREATE TABLE 'users' ('migration_name' VARCHAR(255) UNIQUE)}
|
359
|
+
)
|
360
|
+
@m.create_migration_info_table_if_needed
|
361
|
+
end
|
362
|
+
|
363
|
+
it 'should not try to create the migration info table if it already exists' do
|
364
|
+
@m.should_receive(:migration_info_table_exists?).and_return(true)
|
365
|
+
@m.should_not_receive(:execute)
|
366
|
+
@m.create_migration_info_table_if_needed
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
it 'should quote the name of the migration for use in sql' do
|
371
|
+
@m.quoted_name.should == %{'do_nothing'}
|
372
|
+
end
|
373
|
+
|
374
|
+
it 'should query the adapter to see if the migration_info table exists' do
|
375
|
+
@adapter.should_receive(:storage_exists?).with('migration_info').and_return(true)
|
376
|
+
@m.migration_info_table_exists?.should == true
|
377
|
+
end
|
378
|
+
|
379
|
+
describe '#migration_record' do
|
380
|
+
it 'should query for the migration' do
|
381
|
+
@adapter.should_receive(:query).with(
|
382
|
+
%Q{SELECT 'migration_name' FROM 'users' WHERE 'migration_name' = 'do_nothing'}
|
383
|
+
)
|
384
|
+
@m.migration_record
|
385
|
+
end
|
386
|
+
|
387
|
+
it 'should not try to query if the table does not exist' do
|
388
|
+
@m.stub!(:migration_info_table_exists?).and_return(false)
|
389
|
+
@adapter.should_not_receive(:query)
|
390
|
+
@m.migration_record
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
describe '#needs_up?' do
|
396
|
+
it 'should be true if there is no record' do
|
397
|
+
@m.should_receive(:migration_record).and_return([])
|
398
|
+
@m.needs_up?.should == true
|
399
|
+
end
|
400
|
+
|
401
|
+
it 'should be false if the record exists' do
|
402
|
+
@m.should_receive(:migration_record).and_return([:not_empty])
|
403
|
+
@m.needs_up?.should == false
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'should be true if there is no migration_info table' do
|
407
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
408
|
+
@m.needs_up?.should == true
|
409
|
+
end
|
410
|
+
|
411
|
+
end
|
412
|
+
|
413
|
+
describe '#needs_down?' do
|
414
|
+
it 'should be false if there is no record' do
|
415
|
+
@m.should_receive(:migration_record).and_return([])
|
416
|
+
@m.needs_down?.should == false
|
417
|
+
end
|
418
|
+
|
419
|
+
it 'should be true if the record exists' do
|
420
|
+
@m.should_receive(:migration_record).and_return([:not_empty])
|
421
|
+
@m.needs_down?.should == true
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'should be false if there is no migration_info table' do
|
425
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
426
|
+
@m.needs_down?.should == false
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|
430
|
+
|
431
|
+
it 'should have the adapter quote the migration_info table' do
|
432
|
+
@adapter.should_receive(:quote_table_name).with('migration_info').and_return("'migration_info'")
|
433
|
+
@m.migration_info_table.should == "'migration_info'"
|
434
|
+
end
|
435
|
+
|
436
|
+
it 'should have a quoted migration_name_column' do
|
437
|
+
@adapter.should_receive(:quote_column_name).with('migration_name').and_return("'migration_name'")
|
438
|
+
@m.migration_name_column.should == "'migration_name'"
|
439
|
+
end
|
440
|
+
|
441
|
+
end
|
442
|
+
|
443
|
+
end
|
444
|
+
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|