dm-migrations 0.10.2 → 1.0.0.rc1
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/.gitignore +36 -0
- data/Gemfile +141 -0
- data/Rakefile +2 -3
- data/VERSION +1 -1
- data/dm-migrations.gemspec +50 -18
- data/lib/dm-migrations.rb +2 -0
- data/lib/dm-migrations/adapters/dm-do-adapter.rb +276 -0
- data/lib/dm-migrations/adapters/dm-mysql-adapter.rb +283 -0
- data/lib/dm-migrations/adapters/dm-oracle-adapter.rb +321 -0
- data/lib/dm-migrations/adapters/dm-postgres-adapter.rb +159 -0
- data/lib/dm-migrations/adapters/dm-sqlite-adapter.rb +96 -0
- data/lib/dm-migrations/adapters/dm-sqlserver-adapter.rb +177 -0
- data/lib/dm-migrations/adapters/dm-yaml-adapter.rb +23 -0
- data/lib/dm-migrations/auto_migration.rb +238 -0
- data/lib/dm-migrations/migration.rb +3 -3
- data/lib/dm-migrations/sql.rb +2 -2
- data/lib/dm-migrations/sql/mysql.rb +3 -3
- data/lib/dm-migrations/sql/{postgresql.rb → postgres.rb} +3 -3
- data/lib/dm-migrations/sql/{sqlite3.rb → sqlite.rb} +3 -3
- data/spec/integration/auto_migration_spec.rb +506 -0
- data/spec/integration/migration_runner_spec.rb +12 -2
- data/spec/integration/migration_spec.rb +28 -14
- data/spec/integration/sql_spec.rb +22 -21
- data/spec/isolated/require_after_setup_spec.rb +30 -0
- data/spec/isolated/require_before_setup_spec.rb +30 -0
- data/spec/isolated/require_spec.rb +25 -0
- data/spec/spec_helper.rb +10 -25
- data/spec/unit/migration_spec.rb +320 -319
- data/spec/unit/sql/{postgresql_spec.rb → postgres_spec.rb} +17 -17
- data/spec/unit/sql/{sqlite3_extensions_spec.rb → sqlite_extensions_spec.rb} +14 -14
- data/tasks/local_gemfile.rake +18 -0
- data/tasks/spec.rake +0 -3
- metadata +72 -32
@@ -1,16 +1,26 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe 'The migration runner' do
|
4
|
+
|
5
|
+
supported_by :postgres, :mysql, :sqlite, :oracle, :sqlserver do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
@adapter = DataMapper::Spec.adapter
|
9
|
+
@repository = DataMapper.repository(@adapter.name)
|
10
|
+
end
|
11
|
+
|
5
12
|
describe 'empty migration runner' do
|
6
13
|
it "should return an empty array if no migrations have been defined" do
|
7
14
|
migrations.should be_kind_of(Array)
|
8
15
|
migrations.should have(0).item
|
9
16
|
end
|
10
17
|
end
|
18
|
+
|
11
19
|
describe 'migration runnner' do
|
12
20
|
# set up some 'global' setup and teardown tasks
|
13
21
|
before(:each) do
|
22
|
+
# FIXME workaround because dm-migrations can only handle the :default repo
|
23
|
+
#DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[adapter.to_sym]
|
14
24
|
migration( 1, :create_people_table) { }
|
15
25
|
end
|
16
26
|
|
@@ -1,8 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
describe "A Migration" do
|
4
|
+
|
5
|
+
supported_by :postgres, :mysql, :sqlite, :oracle, :sqlserver do
|
6
|
+
|
5
7
|
describe DataMapper::Migration, 'interface' do
|
8
|
+
|
9
|
+
before(:all) do
|
10
|
+
@adapter = DataMapper::Spec.adapter
|
11
|
+
end
|
12
|
+
|
6
13
|
before do
|
7
14
|
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) { }
|
8
15
|
end
|
@@ -20,10 +27,9 @@ ADAPTERS.each do |adapter|
|
|
20
27
|
end
|
21
28
|
|
22
29
|
it "should have a :database option" do
|
23
|
-
DataMapper.
|
24
|
-
|
25
|
-
m
|
26
|
-
m.instance_variable_get(:@database).name.should == :other
|
30
|
+
adapter = DataMapper::Spec.adapter(:alternate)
|
31
|
+
m = DataMapper::Migration.new(2, :create_dogs_table, :database => :alternate) {}
|
32
|
+
m.instance_variable_get(:@adapter).should == adapter
|
27
33
|
end
|
28
34
|
|
29
35
|
it "should use the default database by default" do
|
@@ -49,15 +55,21 @@ ADAPTERS.each do |adapter|
|
|
49
55
|
[m1, m2, m3, m4].sort.should == [m1, m3, m2, m4]
|
50
56
|
end
|
51
57
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
:
|
56
|
-
|
58
|
+
adapter = DataMapper::Spec.adapter_name
|
59
|
+
|
60
|
+
expected_module_lambda = {
|
61
|
+
:sqlite => lambda { SQL::Sqlite },
|
62
|
+
:mysql => lambda { SQL::Mysql },
|
63
|
+
:postgres => lambda { SQL::Postgres }
|
64
|
+
}[adapter.to_sym]
|
65
|
+
|
66
|
+
expected_module = expected_module_lambda ? expected_module_lambda.call : nil
|
57
67
|
|
58
|
-
|
59
|
-
|
60
|
-
|
68
|
+
if expected_module
|
69
|
+
it "should extend with #{expected_module} when adapter is #{adapter}" do
|
70
|
+
migration = DataMapper::Migration.new(1, :"#{adapter}_adapter_test") { }
|
71
|
+
(class << migration.adapter; self; end).included_modules.should include(expected_module)
|
72
|
+
end
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
@@ -120,5 +132,7 @@ ADAPTERS.each do |adapter|
|
|
120
132
|
end
|
121
133
|
|
122
134
|
end
|
135
|
+
|
123
136
|
end
|
137
|
+
|
124
138
|
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
describe "Using Adapter #{adapter}," do
|
3
|
+
describe "SQL generation" do
|
5
4
|
|
6
|
-
|
7
|
-
DataMapper.repository(*args)
|
8
|
-
end
|
5
|
+
supported_by :postgres, :mysql, :sqlite, :oracle, :sqlserver do
|
9
6
|
|
10
7
|
describe DataMapper::Migration, "#create_table helper" do
|
11
8
|
before :all do
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
|
10
|
+
@adapter = DataMapper::Spec.adapter
|
11
|
+
@repository = DataMapper.repository(@adapter.name)
|
12
|
+
|
13
|
+
case DataMapper::Spec.adapter_name.to_sym
|
14
|
+
when :sqlite then @adapter.extend(SQL::Sqlite)
|
15
|
+
when :mysql then @adapter.extend(SQL::Mysql)
|
16
|
+
when :postgres then @adapter.extend(SQL::Postgres)
|
16
17
|
end
|
18
|
+
|
17
19
|
end
|
18
20
|
|
19
21
|
before do
|
20
|
-
@creator = DataMapper::Migration::TableCreator.new(
|
21
|
-
column :id, DataMapper::
|
22
|
+
@creator = DataMapper::Migration::TableCreator.new(@adapter, :people) do
|
23
|
+
column :id, DataMapper::Property::Serial
|
22
24
|
column :name, 'VARCHAR(50)', :allow_nil => false
|
23
25
|
column :long_string, String, :size => 200
|
24
26
|
end
|
@@ -34,7 +36,7 @@ ADAPTERS.each do |adapter|
|
|
34
36
|
end
|
35
37
|
|
36
38
|
it "should have an adapter" do
|
37
|
-
@creator.instance_eval("@adapter").should ==
|
39
|
+
@creator.instance_eval("@adapter").should == @adapter
|
38
40
|
end
|
39
41
|
|
40
42
|
it "should have an options hash" do
|
@@ -49,7 +51,7 @@ ADAPTERS.each do |adapter|
|
|
49
51
|
end
|
50
52
|
|
51
53
|
it "should quote the table name for the adapter" do
|
52
|
-
@creator.quoted_table_name.should == (
|
54
|
+
@creator.quoted_table_name.should == (DataMapper::Spec.adapter_name.to_sym == :mysql ? '`people`' : '"people"')
|
53
55
|
end
|
54
56
|
|
55
57
|
it "should allow for custom options" do
|
@@ -62,7 +64,7 @@ ADAPTERS.each do |adapter|
|
|
62
64
|
@creator.instance_eval("@columns")[1].type.should match(/NOT NULL/)
|
63
65
|
end
|
64
66
|
|
65
|
-
case
|
67
|
+
case DataMapper::Spec.adapter_name.to_sym
|
66
68
|
when :mysql
|
67
69
|
it "should create an InnoDB database for MySQL" do
|
68
70
|
#can't get an exact == comparison here because character set and collation may differ per connection
|
@@ -102,7 +104,7 @@ ADAPTERS.each do |adapter|
|
|
102
104
|
end
|
103
105
|
|
104
106
|
describe DataMapper::Migration, "version tracking" do
|
105
|
-
before do
|
107
|
+
before(:each) do
|
106
108
|
@migration = DataMapper::Migration.new(1, :create_people_table, :verbose => false) do
|
107
109
|
up { :ran_up }
|
108
110
|
down { :ran_down }
|
@@ -111,8 +113,10 @@ ADAPTERS.each do |adapter|
|
|
111
113
|
@migration.send(:create_migration_info_table_if_needed)
|
112
114
|
end
|
113
115
|
|
116
|
+
after(:each) { DataMapper::Spec.adapter.execute("DROP TABLE migration_info") rescue nil }
|
117
|
+
|
114
118
|
def insert_migration_record
|
115
|
-
DataMapper.
|
119
|
+
DataMapper::Spec.adapter.execute("INSERT INTO migration_info (migration_name) VALUES ('create_people_table')")
|
116
120
|
end
|
117
121
|
|
118
122
|
it "should know if the migration_info table exists" do
|
@@ -120,7 +124,7 @@ ADAPTERS.each do |adapter|
|
|
120
124
|
end
|
121
125
|
|
122
126
|
it "should know if the migration_info table does not exist" do
|
123
|
-
|
127
|
+
DataMapper::Spec.adapter.execute("DROP TABLE migration_info") rescue nil
|
124
128
|
@migration.send(:migration_info_table_exists?).should be_false
|
125
129
|
end
|
126
130
|
|
@@ -153,7 +157,7 @@ ADAPTERS.each do |adapter|
|
|
153
157
|
# TODO how to i call the adapter's #escape_sql method?
|
154
158
|
|
155
159
|
it "should create the migration_info table if it doesn't exist" do
|
156
|
-
|
160
|
+
DataMapper::Spec.adapter.execute("DROP TABLE migration_info")
|
157
161
|
@migration.send(:migration_info_table_exists?).should be_false
|
158
162
|
@migration.send(:create_migration_info_table_if_needed)
|
159
163
|
@migration.send(:migration_info_table_exists?).should be_true
|
@@ -181,9 +185,6 @@ ADAPTERS.each do |adapter|
|
|
181
185
|
@migration.perform_down.should_not == :ran_down
|
182
186
|
end
|
183
187
|
|
184
|
-
after do
|
185
|
-
repository.adapter.execute("DELETE FROM migration_info") if @migration.send(:migration_info_table_exists?)
|
186
|
-
end
|
187
188
|
end
|
188
189
|
end
|
189
190
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'isolated/require_spec'
|
3
|
+
require 'dm-core/spec/setup'
|
4
|
+
require 'dm-core/spec/lib/adapter_helpers'
|
5
|
+
|
6
|
+
# To really test this behavior, this spec needs to be run in isolation and not
|
7
|
+
# as part of the typical rake spec run, which requires dm-transactions upfront
|
8
|
+
|
9
|
+
describe "require 'dm-migrations' after calling DataMapper.setup" do
|
10
|
+
extend DataMapper::Spec::Adapters::Helpers
|
11
|
+
|
12
|
+
before(:all) do
|
13
|
+
|
14
|
+
@adapter = DataMapper::Spec.adapter
|
15
|
+
require 'dm-migrations'
|
16
|
+
|
17
|
+
class ::Person
|
18
|
+
include DataMapper::Resource
|
19
|
+
property :id, Serial
|
20
|
+
end
|
21
|
+
|
22
|
+
@model = Person
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
supported_by :postgres, :mysql, :sqlite, :oracle, :sqlserver do
|
27
|
+
it_should_behave_like "require 'dm-migrations'"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'isolated/require_spec'
|
3
|
+
require 'dm-core/spec/setup'
|
4
|
+
require 'dm-core/spec/lib/adapter_helpers'
|
5
|
+
|
6
|
+
# To really test this behavior, this spec needs to be run in isolation and not
|
7
|
+
# as part of the typical rake spec run, which requires dm-transactions upfront
|
8
|
+
|
9
|
+
describe "require 'dm-migrations' before calling DataMapper.setup" do
|
10
|
+
extend DataMapper::Spec::Adapters::Helpers
|
11
|
+
|
12
|
+
before(:all) do
|
13
|
+
|
14
|
+
require 'dm-migrations'
|
15
|
+
@adapter = DataMapper::Spec.adapter
|
16
|
+
|
17
|
+
class ::Person
|
18
|
+
include DataMapper::Resource
|
19
|
+
property :id, Serial
|
20
|
+
end
|
21
|
+
|
22
|
+
@model = Person
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
supported_by :postgres, :mysql, :sqlite, :oracle, :sqlserver do
|
27
|
+
it_should_behave_like "require 'dm-migrations'"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
shared_examples_for "require 'dm-migrations'" do
|
2
|
+
|
3
|
+
it "should include the migration api in the DataMapper namespace" do
|
4
|
+
DataMapper.respond_to?(:migrate! ).should be_true
|
5
|
+
DataMapper.respond_to?(:auto_migrate! ).should be_true
|
6
|
+
DataMapper.respond_to?(:auto_upgrade! ).should be_true
|
7
|
+
DataMapper.respond_to?(:auto_migrate_up!, true).should be_true
|
8
|
+
DataMapper.respond_to?(:auto_migrate_down!, true).should be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
%w[Repository Model].each do |name|
|
12
|
+
it "should include the migration api in DataMapper::#{name}" do
|
13
|
+
(DataMapper.const_get(name) < DataMapper::Migrations.const_get(name)).should be_true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should include the migration api into the adapter" do
|
18
|
+
@adapter.respond_to?(:storage_exists? ).should be_true
|
19
|
+
@adapter.respond_to?(:field_exists? ).should be_true
|
20
|
+
@adapter.respond_to?(:upgrade_model_storage).should be_true
|
21
|
+
@adapter.respond_to?(:create_model_storage ).should be_true
|
22
|
+
@adapter.respond_to?(:destroy_model_storage).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,31 +1,16 @@
|
|
1
|
-
require '
|
1
|
+
require 'dm-migrations'
|
2
|
+
require 'dm-migrations/migration_runner'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
require 'dm-core'
|
4
|
+
require 'dm-core/spec/setup'
|
5
|
+
require 'dm-core/spec/lib/adapter_helpers'
|
6
|
+
require 'dm-core/spec/lib/spec_helper'
|
7
7
|
|
8
|
-
|
9
|
-
$LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
|
8
|
+
Spec::Runner.configure do |config|
|
10
9
|
|
11
|
-
|
12
|
-
require 'dm-migrations/migration_runner'
|
10
|
+
config.extend(DataMapper::Spec::Adapters::Helpers)
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
begin
|
17
|
-
DataMapper.setup(name, default_uri)
|
18
|
-
DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
|
19
|
-
ADAPTERS << name
|
20
|
-
true
|
21
|
-
rescue LoadError => e
|
22
|
-
warn "Could not load do_#{name}: #{e}"
|
23
|
-
false
|
12
|
+
config.after :all do
|
13
|
+
DataMapper::Spec.cleanup_models
|
24
14
|
end
|
25
|
-
end
|
26
|
-
|
27
|
-
ENV['ADAPTER'] ||= 'sqlite3'
|
28
15
|
|
29
|
-
|
30
|
-
load_driver(:mysql, 'mysql://localhost/dm_core_test')
|
31
|
-
load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
|
16
|
+
end
|
data/spec/unit/migration_spec.rb
CHANGED
@@ -1,443 +1,444 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe 'Migration' do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
[:position, :name, :database, :adapter].each do |meth|
|
14
|
-
it "should respond to ##{meth}" do
|
15
|
-
@m.should respond_to(meth)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe 'initialization' do
|
20
|
-
it 'should set @position from the given position' do
|
21
|
-
@m.instance_variable_get(:@position).should == 1
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'should set @name from the given name' do
|
25
|
-
@m.instance_variable_get(:@name).should == :do_nothing
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'should set @options from the options hash' do
|
29
|
-
@m.instance_variable_get(:@options).should == {}
|
4
|
+
supported_by :postgres, :mysql, :sqlite do
|
5
|
+
before do
|
6
|
+
@adapter = mock('adapter', :class => DataMapper::Spec.adapter.class)
|
7
|
+
@repo = mock('DataMapper.repository', :adapter => @adapter)
|
8
|
+
DataMapper.stub!(:repository).and_return(@repo)
|
9
|
+
@m = DataMapper::Migration.new(1, :do_nothing, {}) {}
|
10
|
+
@m.stub!(:write) # silence any output
|
30
11
|
end
|
31
12
|
|
32
|
-
|
33
|
-
|
34
|
-
|
13
|
+
[:position, :name, :database, :adapter].each do |meth|
|
14
|
+
it "should respond to ##{meth}" do
|
15
|
+
@m.should respond_to(meth)
|
16
|
+
end
|
35
17
|
end
|
36
18
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
19
|
+
describe 'initialization' do
|
20
|
+
it 'should set @position from the given position' do
|
21
|
+
@m.instance_variable_get(:@position).should == 1
|
22
|
+
end
|
41
23
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
24
|
+
it 'should set @name from the given name' do
|
25
|
+
@m.instance_variable_get(:@name).should == :do_nothing
|
26
|
+
end
|
46
27
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
end
|
28
|
+
it 'should set @options from the options hash' do
|
29
|
+
@m.instance_variable_get(:@options).should == {}
|
30
|
+
end
|
51
31
|
|
52
|
-
|
53
|
-
|
54
|
-
lambda {
|
32
|
+
it 'should set @database from the default repository if no :database option is given' do
|
33
|
+
DataMapper.should_receive(:repository).with(:default).and_return(@repo)
|
55
34
|
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'should set @verbose from the options hash' do
|
60
|
-
m = DataMapper::Migration.new(1, :do_nothing, :verbose => false) {}
|
61
|
-
m.instance_variable_get(:@verbose).should be_false
|
62
|
-
end
|
35
|
+
end
|
63
36
|
|
64
|
-
|
65
|
-
|
66
|
-
|
37
|
+
it 'should set @database to the repository specified with the :database option' do
|
38
|
+
DataMapper.should_receive(:repository).with(:foobar).and_return(@repo)
|
39
|
+
DataMapper::Migration.new(1, :do_nothing, :database => :foobar) {}
|
40
|
+
end
|
67
41
|
|
68
|
-
|
69
|
-
|
70
|
-
|
42
|
+
it 'should determine the class of the adapter to be extended' do
|
43
|
+
@adapter.should_receive(:class).and_return(DataMapper::Spec.adapter.class)
|
44
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
45
|
+
end
|
71
46
|
|
72
|
-
|
73
|
-
|
74
|
-
|
47
|
+
it 'should extend the adapter with the right module' do
|
48
|
+
@adapter.should_receive(:extend).with(SQL.const_get(DataMapper::Spec.adapter_name.capitalize))
|
49
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
50
|
+
end
|
75
51
|
|
76
|
-
|
52
|
+
it 'should raise "Unsupported adapter" on an unknown adapter' do
|
53
|
+
@adapter.should_receive(:class).any_number_of_times.and_return("InvalidAdapter")
|
54
|
+
lambda {
|
55
|
+
DataMapper::Migration.new(1, :do_nothing, {}) {}
|
56
|
+
}.should raise_error
|
57
|
+
end
|
77
58
|
|
78
|
-
|
59
|
+
it 'should set @verbose from the options hash' do
|
60
|
+
m = DataMapper::Migration.new(1, :do_nothing, :verbose => false) {}
|
61
|
+
m.instance_variable_get(:@verbose).should be_false
|
62
|
+
end
|
79
63
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
@m.instance_variable_get(:@up_action).should == action
|
84
|
-
end
|
64
|
+
it 'should set @verbose to true by default' do
|
65
|
+
@m.instance_variable_get(:@verbose).should be_true
|
66
|
+
end
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@m.instance_variable_get(:@down_action).should == action
|
90
|
-
end
|
68
|
+
it 'should set the @up_action to an empty block' do
|
69
|
+
@m.instance_variable_get(:@up_action).should be_kind_of(Proc)
|
70
|
+
end
|
91
71
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
@m.instance_variable_set(:@up_action, @up_action)
|
96
|
-
@m.stub!(:needs_up?).and_return(true)
|
97
|
-
@m.stub!(:update_migration_info)
|
98
|
-
end
|
72
|
+
it 'should set the @down_action to an empty block' do
|
73
|
+
@m.instance_variable_get(:@down_action).should be_kind_of(Proc)
|
74
|
+
end
|
99
75
|
|
100
|
-
|
101
|
-
@up_action.should_receive(:call).and_return(:result)
|
102
|
-
@m.perform_up.should == :result
|
103
|
-
end
|
76
|
+
it 'should evaluate the given block'
|
104
77
|
|
105
|
-
it 'should output a status message with the position and name of the migration' do
|
106
|
-
@m.should_receive(:write).with(/Performing Up Migration #1: do_nothing/)
|
107
|
-
@m.perform_up
|
108
78
|
end
|
109
79
|
|
110
|
-
it 'should
|
111
|
-
|
112
|
-
@
|
113
|
-
@m.
|
80
|
+
it 'should set the @up_action when #up is called with a block' do
|
81
|
+
action = lambda {}
|
82
|
+
@m.up(&action)
|
83
|
+
@m.instance_variable_get(:@up_action).should == action
|
114
84
|
end
|
115
85
|
|
116
|
-
it 'should
|
117
|
-
|
118
|
-
@m.
|
86
|
+
it 'should set the @up_action when #up is called with a block' do
|
87
|
+
action = lambda {}
|
88
|
+
@m.down(&action)
|
89
|
+
@m.instance_variable_get(:@down_action).should == action
|
119
90
|
end
|
120
91
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
92
|
+
describe 'perform_up' do
|
93
|
+
before do
|
94
|
+
@up_action = mock('proc', :call => true)
|
95
|
+
@m.instance_variable_set(:@up_action, @up_action)
|
96
|
+
@m.stub!(:needs_up?).and_return(true)
|
97
|
+
@m.stub!(:update_migration_info)
|
98
|
+
end
|
126
99
|
|
127
|
-
|
100
|
+
it 'should call the action assigned to @up_action and return the result' do
|
101
|
+
@up_action.should_receive(:call).and_return(:result)
|
102
|
+
@m.perform_up.should == :result
|
103
|
+
end
|
128
104
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
@m.stub!(:needs_down?).and_return(true)
|
134
|
-
@m.stub!(:update_migration_info)
|
135
|
-
end
|
105
|
+
it 'should output a status message with the position and name of the migration' do
|
106
|
+
@m.should_receive(:write).with(/Performing Up Migration #1: do_nothing/)
|
107
|
+
@m.perform_up
|
108
|
+
end
|
136
109
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
110
|
+
it 'should not run if it doesnt need to be' do
|
111
|
+
@m.should_receive(:needs_up?).and_return(false)
|
112
|
+
@up_action.should_not_receive(:call)
|
113
|
+
@m.perform_up
|
114
|
+
end
|
141
115
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
116
|
+
it 'should update the migration info table' do
|
117
|
+
@m.should_receive(:update_migration_info).with(:up)
|
118
|
+
@m.perform_up
|
119
|
+
end
|
146
120
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
121
|
+
it 'should not update the migration info table if the migration does not need run' do
|
122
|
+
@m.should_receive(:needs_up?).and_return(false)
|
123
|
+
@m.should_not_receive(:update_migration_info)
|
124
|
+
@m.perform_up
|
125
|
+
end
|
152
126
|
|
153
|
-
it 'should update the migration info table' do
|
154
|
-
@m.should_receive(:update_migration_info).with(:down)
|
155
|
-
@m.perform_down
|
156
127
|
end
|
157
128
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
129
|
+
describe 'perform_down' do
|
130
|
+
before do
|
131
|
+
@down_action = mock('proc', :call => true)
|
132
|
+
@m.instance_variable_set(:@down_action, @down_action)
|
133
|
+
@m.stub!(:needs_down?).and_return(true)
|
134
|
+
@m.stub!(:update_migration_info)
|
135
|
+
end
|
163
136
|
|
164
|
-
|
137
|
+
it 'should call the action assigned to @down_action and return the result' do
|
138
|
+
@down_action.should_receive(:call).and_return(:result)
|
139
|
+
@m.perform_down.should == :result
|
140
|
+
end
|
165
141
|
|
166
|
-
|
142
|
+
it 'should output a status message with the position and name of the migration' do
|
143
|
+
@m.should_receive(:write).with(/Performing Down Migration #1: do_nothing/)
|
144
|
+
@m.perform_down
|
145
|
+
end
|
167
146
|
|
168
|
-
|
169
|
-
|
170
|
-
@
|
147
|
+
it 'should not run if it doesnt need to be' do
|
148
|
+
@m.should_receive(:needs_down?).and_return(false)
|
149
|
+
@down_action.should_not_receive(:call)
|
150
|
+
@m.perform_down
|
171
151
|
end
|
172
152
|
|
173
|
-
it 'should
|
174
|
-
@
|
175
|
-
@m.
|
153
|
+
it 'should update the migration info table' do
|
154
|
+
@m.should_receive(:update_migration_info).with(:down)
|
155
|
+
@m.perform_down
|
176
156
|
end
|
177
157
|
|
178
|
-
it 'should
|
179
|
-
@m.should_receive(:
|
180
|
-
@m.
|
158
|
+
it 'should not update the migration info table if the migration does not need run' do
|
159
|
+
@m.should_receive(:needs_down?).and_return(false)
|
160
|
+
@m.should_not_receive(:update_migration_info)
|
161
|
+
@m.perform_down
|
181
162
|
end
|
163
|
+
|
182
164
|
end
|
183
165
|
|
184
|
-
describe '
|
185
|
-
before do
|
186
|
-
@m.stub!(:execute) # don't actually run anything
|
187
|
-
end
|
166
|
+
describe 'methods used in the action blocks' do
|
188
167
|
|
189
|
-
describe '#
|
168
|
+
describe '#execute' do
|
190
169
|
before do
|
191
|
-
@
|
192
|
-
SQL::TableCreator.stub!(:new).and_return(@tc)
|
170
|
+
@adapter.stub!(:execute)
|
193
171
|
end
|
194
172
|
|
195
|
-
it 'should
|
196
|
-
|
197
|
-
@m.
|
173
|
+
it 'should send the SQL it its executing to the adapter execute method' do
|
174
|
+
@adapter.should_receive(:execute).with('SELECT SOME SQL')
|
175
|
+
@m.execute('SELECT SOME SQL')
|
198
176
|
end
|
199
177
|
|
200
|
-
it 'should
|
201
|
-
@
|
202
|
-
@m.
|
178
|
+
it 'should output the SQL it is executing' do
|
179
|
+
@m.should_receive(:write).with(/SELECT SOME SQL/)
|
180
|
+
@m.execute('SELECT SOME SQL')
|
203
181
|
end
|
182
|
+
end
|
204
183
|
|
205
|
-
|
206
|
-
|
207
|
-
@m.
|
184
|
+
describe 'helpers' do
|
185
|
+
before do
|
186
|
+
@m.stub!(:execute) # don't actually run anything
|
208
187
|
end
|
209
188
|
|
210
|
-
|
189
|
+
describe '#create_table' do
|
190
|
+
before do
|
191
|
+
@tc = mock('TableCreator', :to_sql => 'CREATE TABLE')
|
192
|
+
SQL::TableCreator.stub!(:new).and_return(@tc)
|
193
|
+
end
|
211
194
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
end
|
195
|
+
it 'should create a new TableCreator object' do
|
196
|
+
SQL::TableCreator.should_receive(:new).with(@adapter, :users, {}).and_return(@tc)
|
197
|
+
@m.create_table(:users) { }
|
198
|
+
end
|
217
199
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
end
|
200
|
+
it 'should convert the TableCreator object to an sql statement' do
|
201
|
+
@tc.should_receive(:to_sql).and_return('CREATE TABLE')
|
202
|
+
@m.create_table(:users) { }
|
203
|
+
end
|
223
204
|
|
224
|
-
|
205
|
+
it 'should execute the create table sql' do
|
206
|
+
@m.should_receive(:execute).with('CREATE TABLE')
|
207
|
+
@m.create_table(:users) { }
|
208
|
+
end
|
225
209
|
|
226
|
-
describe '#modify_table' do
|
227
|
-
before do
|
228
|
-
@tm = mock('TableModifier', :statements => [])
|
229
|
-
SQL::TableModifier.stub!(:new).and_return(@tm)
|
230
210
|
end
|
231
211
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
212
|
+
describe '#drop_table' do
|
213
|
+
it 'should quote the table name' do
|
214
|
+
@adapter.should_receive(:quote_name).with('users')
|
215
|
+
@m.drop_table :users
|
216
|
+
end
|
236
217
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
218
|
+
it 'should execute the DROP TABLE sql for the table' do
|
219
|
+
@adapter.stub!(:quote_name).and_return("'users'")
|
220
|
+
@m.should_receive(:execute).with(%{DROP TABLE 'users'})
|
221
|
+
@m.drop_table :users
|
222
|
+
end
|
241
223
|
|
242
|
-
it 'should iterate over the statements and execute each one' do
|
243
|
-
@tm.should_receive(:statements).and_return(['SELECT 1', 'SELECT 2'])
|
244
|
-
@m.should_receive(:execute).with('SELECT 1')
|
245
|
-
@m.should_receive(:execute).with('SELECT 2')
|
246
|
-
@m.modify_table(:users){ }
|
247
224
|
end
|
248
225
|
|
249
|
-
|
226
|
+
describe '#modify_table' do
|
227
|
+
before do
|
228
|
+
@tm = mock('TableModifier', :statements => [])
|
229
|
+
SQL::TableModifier.stub!(:new).and_return(@tm)
|
230
|
+
end
|
250
231
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
232
|
+
it 'should create a new TableModifier object' do
|
233
|
+
SQL::TableModifier.should_receive(:new).with(@adapter, :users, {}).and_return(@tm)
|
234
|
+
@m.modify_table(:users){ }
|
235
|
+
end
|
255
236
|
|
256
|
-
|
257
|
-
|
237
|
+
it 'should get the statements from the TableModifier object' do
|
238
|
+
@tm.should_receive(:statements).and_return([])
|
239
|
+
@m.modify_table(:users){ }
|
240
|
+
end
|
258
241
|
|
259
|
-
|
260
|
-
|
261
|
-
|
242
|
+
it 'should iterate over the statements and execute each one' do
|
243
|
+
@tm.should_receive(:statements).and_return(['SELECT 1', 'SELECT 2'])
|
244
|
+
@m.should_receive(:execute).with('SELECT 1')
|
245
|
+
@m.should_receive(:execute).with('SELECT 2')
|
246
|
+
@m.modify_table(:users){ }
|
247
|
+
end
|
262
248
|
|
263
|
-
(m1 <=> m2).should == -1
|
264
249
|
end
|
265
250
|
|
266
|
-
|
251
|
+
describe 'sorting' do
|
252
|
+
it 'should order things by position' do
|
253
|
+
m1 = DataMapper::Migration.new(1, :do_nothing){}
|
254
|
+
m2 = DataMapper::Migration.new(2, :do_nothing_else){}
|
267
255
|
|
268
|
-
|
269
|
-
describe '#say' do
|
270
|
-
it 'should output the message' do
|
271
|
-
@m.should_receive(:write).with(/Paul/)
|
272
|
-
@m.say("Paul")
|
256
|
+
(m1 <=> m2).should == -1
|
273
257
|
end
|
274
258
|
|
275
|
-
it 'should
|
276
|
-
|
277
|
-
|
278
|
-
end
|
259
|
+
it 'should order things by name when they have the same position' do
|
260
|
+
m1 = DataMapper::Migration.new(1, :do_nothing_a){}
|
261
|
+
m2 = DataMapper::Migration.new(1, :do_nothing_b){}
|
279
262
|
|
280
|
-
|
281
|
-
@m.should_receive(:write).with(/^\s{3}/)
|
282
|
-
@m.say("Paul", 3)
|
263
|
+
(m1 <=> m2).should == -1
|
283
264
|
end
|
265
|
+
|
284
266
|
end
|
285
267
|
|
286
|
-
describe '
|
287
|
-
|
288
|
-
|
268
|
+
describe 'formatting output' do
|
269
|
+
describe '#say' do
|
270
|
+
it 'should output the message' do
|
271
|
+
@m.should_receive(:write).with(/Paul/)
|
272
|
+
@m.say("Paul")
|
273
|
+
end
|
274
|
+
|
275
|
+
it 'should indent the message with 4 spaces by default' do
|
276
|
+
@m.should_receive(:write).with(/^\s{4}/)
|
277
|
+
@m.say("Paul")
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'should indext the message with a given number of spaces' do
|
281
|
+
@m.should_receive(:write).with(/^\s{3}/)
|
282
|
+
@m.say("Paul", 3)
|
283
|
+
end
|
289
284
|
end
|
290
285
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
286
|
+
describe '#say_with_time' do
|
287
|
+
before do
|
288
|
+
@m.stub!(:say)
|
289
|
+
end
|
295
290
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
end
|
291
|
+
it 'should say the message with an indent of 2' do
|
292
|
+
@m.should_receive(:say).with("Paul", 2)
|
293
|
+
@m.say_with_time("Paul"){}
|
294
|
+
end
|
301
295
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
296
|
+
it 'should output the time it took' do
|
297
|
+
@m.should_receive(:say).with(/\d+/, 2)
|
298
|
+
@m.say_with_time("Paul"){}
|
299
|
+
end
|
306
300
|
end
|
307
301
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
302
|
+
describe '#write' do
|
303
|
+
before do
|
304
|
+
# need a new migration object, because the main one had #write stubbed to silence output
|
305
|
+
@m = DataMapper::Migration.new(1, :do_nothing) {}
|
306
|
+
end
|
312
307
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
end
|
308
|
+
it 'should puts the message' do
|
309
|
+
@m.should_receive(:puts).with("Paul")
|
310
|
+
@m.write("Paul")
|
311
|
+
end
|
318
312
|
|
319
|
-
|
313
|
+
it 'should not puts the message if @verbose is false' do
|
314
|
+
@m.instance_variable_set(:@verbose, false)
|
315
|
+
@m.should_not_receive(:puts)
|
316
|
+
@m.write("Paul")
|
317
|
+
end
|
320
318
|
|
321
|
-
|
319
|
+
end
|
322
320
|
|
323
|
-
describe 'working with the migration_info table' do
|
324
|
-
before do
|
325
|
-
@adapter.stub!(:storage_exists?).and_return(true)
|
326
|
-
# --- Please remove stubs ---
|
327
|
-
@adapter.stub!(:quote_name).and_return { |name| "'#{name}'" }
|
328
321
|
end
|
329
322
|
|
330
|
-
describe '
|
331
|
-
|
332
|
-
@
|
333
|
-
|
334
|
-
)
|
335
|
-
@m.update_migration_info(:up)
|
323
|
+
describe 'working with the migration_info table' do
|
324
|
+
before do
|
325
|
+
@adapter.stub!(:storage_exists?).and_return(true)
|
326
|
+
# --- Please remove stubs ---
|
327
|
+
@adapter.stub!(:quote_name).and_return { |name| "'#{name}'" }
|
336
328
|
end
|
337
329
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
330
|
+
describe '#update_migration_info' do
|
331
|
+
it 'should add a record of the migration' do
|
332
|
+
@m.should_receive(:execute).with(
|
333
|
+
%Q{INSERT INTO 'migration_info' ('migration_name') VALUES ('do_nothing')}
|
334
|
+
)
|
335
|
+
@m.update_migration_info(:up)
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should remove the record of the migration' do
|
339
|
+
@m.should_receive(:execute).with(
|
340
|
+
%Q{DELETE FROM 'migration_info' WHERE 'migration_name' = 'do_nothing'}
|
341
|
+
)
|
342
|
+
@m.update_migration_info(:down)
|
343
|
+
end
|
344
|
+
|
345
|
+
it 'should try to create the migration_info table' do
|
346
|
+
@m.should_receive(:create_migration_info_table_if_needed)
|
347
|
+
@m.update_migration_info(:up)
|
348
|
+
end
|
343
349
|
end
|
344
350
|
|
345
|
-
|
346
|
-
|
347
|
-
|
351
|
+
describe '#create_migration_info_table_if_needed' do
|
352
|
+
it 'should create the migration info table' do
|
353
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
354
|
+
@m.should_receive(:execute).with(
|
355
|
+
%Q{CREATE TABLE 'migration_info' ('migration_name' VARCHAR(255) UNIQUE)}
|
356
|
+
)
|
357
|
+
@m.create_migration_info_table_if_needed
|
358
|
+
end
|
359
|
+
|
360
|
+
it 'should not try to create the migration info table if it already exists' do
|
361
|
+
@m.should_receive(:migration_info_table_exists?).and_return(true)
|
362
|
+
@m.should_not_receive(:execute)
|
363
|
+
@m.create_migration_info_table_if_needed
|
364
|
+
end
|
348
365
|
end
|
349
|
-
end
|
350
366
|
|
351
|
-
|
352
|
-
|
353
|
-
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
354
|
-
@m.should_receive(:execute).with(
|
355
|
-
%Q{CREATE TABLE 'migration_info' ('migration_name' VARCHAR(255) UNIQUE)}
|
356
|
-
)
|
357
|
-
@m.create_migration_info_table_if_needed
|
367
|
+
it 'should quote the name of the migration for use in sql' do
|
368
|
+
@m.quoted_name.should == %{'do_nothing'}
|
358
369
|
end
|
359
370
|
|
360
|
-
it 'should
|
361
|
-
@
|
362
|
-
@m.
|
363
|
-
@m.create_migration_info_table_if_needed
|
371
|
+
it 'should query the adapter to see if the migration_info table exists' do
|
372
|
+
@adapter.should_receive(:storage_exists?).with('migration_info').and_return(true)
|
373
|
+
@m.migration_info_table_exists?.should == true
|
364
374
|
end
|
365
|
-
end
|
366
375
|
|
367
|
-
|
368
|
-
|
369
|
-
|
376
|
+
describe '#migration_record' do
|
377
|
+
it 'should query for the migration' do
|
378
|
+
@adapter.should_receive(:select).with(
|
379
|
+
%Q{SELECT 'migration_name' FROM 'migration_info' WHERE 'migration_name' = 'do_nothing'}
|
380
|
+
)
|
381
|
+
@m.migration_record
|
382
|
+
end
|
370
383
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
384
|
+
it 'should not try to query if the table does not exist' do
|
385
|
+
@m.stub!(:migration_info_table_exists?).and_return(false)
|
386
|
+
@adapter.should_not_receive(:select)
|
387
|
+
@m.migration_record
|
388
|
+
end
|
375
389
|
|
376
|
-
describe '#migration_record' do
|
377
|
-
it 'should query for the migration' do
|
378
|
-
@adapter.should_receive(:select).with(
|
379
|
-
%Q{SELECT 'migration_name' FROM 'migration_info' WHERE 'migration_name' = 'do_nothing'}
|
380
|
-
)
|
381
|
-
@m.migration_record
|
382
390
|
end
|
383
391
|
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
392
|
+
describe '#needs_up?' do
|
393
|
+
it 'should be true if there is no record' do
|
394
|
+
@m.should_receive(:migration_record).and_return([])
|
395
|
+
@m.needs_up?.should == true
|
396
|
+
end
|
389
397
|
|
390
|
-
|
398
|
+
it 'should be false if the record exists' do
|
399
|
+
@m.should_receive(:migration_record).and_return([:not_empty])
|
400
|
+
@m.needs_up?.should == false
|
401
|
+
end
|
391
402
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
end
|
403
|
+
it 'should be true if there is no migration_info table' do
|
404
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
405
|
+
@m.needs_up?.should == true
|
406
|
+
end
|
397
407
|
|
398
|
-
it 'should be false if the record exists' do
|
399
|
-
@m.should_receive(:migration_record).and_return([:not_empty])
|
400
|
-
@m.needs_up?.should == false
|
401
408
|
end
|
402
409
|
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
410
|
+
describe '#needs_down?' do
|
411
|
+
it 'should be false if there is no record' do
|
412
|
+
@m.should_receive(:migration_record).and_return([])
|
413
|
+
@m.needs_down?.should == false
|
414
|
+
end
|
407
415
|
|
408
|
-
|
416
|
+
it 'should be true if the record exists' do
|
417
|
+
@m.should_receive(:migration_record).and_return([:not_empty])
|
418
|
+
@m.needs_down?.should == true
|
419
|
+
end
|
409
420
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
end
|
421
|
+
it 'should be false if there is no migration_info table' do
|
422
|
+
@m.should_receive(:migration_info_table_exists?).and_return(false)
|
423
|
+
@m.needs_down?.should == false
|
424
|
+
end
|
415
425
|
|
416
|
-
it 'should be true if the record exists' do
|
417
|
-
@m.should_receive(:migration_record).and_return([:not_empty])
|
418
|
-
@m.needs_down?.should == true
|
419
426
|
end
|
420
427
|
|
421
|
-
it 'should
|
422
|
-
@
|
423
|
-
@m.
|
428
|
+
it 'should have the adapter quote the migration_info table' do
|
429
|
+
@adapter.should_receive(:quote_name).with('migration_info').and_return("'migration_info'")
|
430
|
+
@m.migration_info_table.should == "'migration_info'"
|
424
431
|
end
|
425
432
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
@m.migration_info_table.should == "'migration_info'"
|
431
|
-
end
|
433
|
+
it 'should have a quoted migration_name_column' do
|
434
|
+
@adapter.should_receive(:quote_name).with('migration_name').and_return("'migration_name'")
|
435
|
+
@m.migration_name_column.should == "'migration_name'"
|
436
|
+
end
|
432
437
|
|
433
|
-
it 'should have a quoted migration_name_column' do
|
434
|
-
@adapter.should_receive(:quote_name).with('migration_name').and_return("'migration_name'")
|
435
|
-
@m.migration_name_column.should == "'migration_name'"
|
436
438
|
end
|
437
439
|
|
438
440
|
end
|
439
441
|
|
440
442
|
end
|
441
|
-
|
442
443
|
end
|
443
444
|
end
|