standalone_migrations 0.4.5 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +23 -1
- data/Rakefile +19 -4
- data/VERSION +1 -1
- data/lib/tasks/standalone_migrations.rb +238 -225
- data/spec/standalone_migrations_spec.rb +75 -2
- data/standalone_migrations.gemspec +4 -3
- metadata +16 -4
data/README.markdown
CHANGED
@@ -12,6 +12,7 @@ Add to `Rakefile` in your projects base directory:
|
|
12
12
|
# t.migrations = "db/migrations"
|
13
13
|
# t.config = "db/config.yml"
|
14
14
|
# t.schema = "db/schema.rb"
|
15
|
+
# t.sub_namespace = "dbname"
|
15
16
|
# t.env = "DB"
|
16
17
|
# t.default_env = "development"
|
17
18
|
# t.verbose = true
|
@@ -77,6 +78,27 @@ If you're lazy and want to just execute raw SQL:
|
|
77
78
|
|
78
79
|
rake db:migrate:up VERSION=20081220234130
|
79
80
|
|
81
|
+
## Sub-namespacing
|
82
|
+
|
83
|
+
When working with multiple databases in a single application it is convenient
|
84
|
+
to have separate sets of tasks for each database. This is accomplished with
|
85
|
+
sub_namespace parameter - for example, given the following declaration:
|
86
|
+
|
87
|
+
MigratorTasks.new do |t|
|
88
|
+
t.migrations = "db/migrate/widgets"
|
89
|
+
t.sub_namespace = "widgets"
|
90
|
+
...
|
91
|
+
end
|
92
|
+
|
93
|
+
The following tasks will be created:
|
94
|
+
|
95
|
+
db:widgets:new_migration
|
96
|
+
db:widgets:migrate
|
97
|
+
...
|
98
|
+
|
99
|
+
And migrations for this database would be created in db/migrate/widgets
|
100
|
+
subdirectory.
|
101
|
+
|
80
102
|
Contributors
|
81
103
|
============
|
82
104
|
This work is based on [Lincoln Stoll's blog post](http://lstoll.net/2008/04/stand-alone-activerecord-migrations/) and [David Welton's post](http://journal.dedasys.com/2007/01/28/using-migrations-outside-of-rails).
|
@@ -86,4 +108,4 @@ This work is based on [Lincoln Stoll's blog post](http://lstoll.net/2008/04/stan
|
|
86
108
|
- [Eric Lindvall](http://bitmonkey.net)
|
87
109
|
- [Steve Hodgkiss](http://stevehodgkiss.com/)
|
88
110
|
- [Rich Meyers](https://github.com/richmeyers)
|
89
|
-
- [Wes Bailey](http://exposinggotchas.blogspot.com/)
|
111
|
+
- [Wes Bailey](http://exposinggotchas.blogspot.com/)
|
data/Rakefile
CHANGED
@@ -1,12 +1,29 @@
|
|
1
1
|
task :default => :spec
|
2
|
-
|
3
|
-
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
rescue LoadError => e
|
6
|
+
$stderr.puts "RSpec 2, or one of its dependencies, is not available:"
|
7
|
+
$stderr.puts "#{e.class}: #{e.message}"
|
8
|
+
$stderr.puts "Install it with: sudo gem install rspec"
|
9
|
+
$stderr.puts "Test-related tasks will not be available."
|
10
|
+
$stderr.puts "If you have RSpec 1 installed you can try running the tests with:"
|
11
|
+
$stderr.puts " spec spec"
|
12
|
+
$stderr.puts "However, RSpec 1 is not officially supported."
|
13
|
+
else
|
14
|
+
RSpec::Core::RakeTask.new {|t| t.rspec_opts = ['--color']}
|
15
|
+
end
|
4
16
|
|
5
17
|
# rake install -> install gem locally (for tests)
|
6
18
|
# rake release -> push to github and release to gemcutter
|
7
19
|
# rake version:bump:patch -> increase version and add a git-tag
|
8
20
|
begin
|
9
21
|
require 'jeweler'
|
22
|
+
rescue LoadError => e
|
23
|
+
$stderr.puts "Jeweler, or one of its dependencies, is not available:"
|
24
|
+
$stderr.puts "#{e.class}: #{e.message}"
|
25
|
+
$stderr.puts "Install it with: sudo gem install jeweler"
|
26
|
+
else
|
10
27
|
Jeweler::Tasks.new do |gem|
|
11
28
|
gem.name = 'standalone_migrations'
|
12
29
|
gem.summary = "A thin wrapper to use Rails Migrations in non Rails projects"
|
@@ -18,6 +35,4 @@ begin
|
|
18
35
|
end
|
19
36
|
|
20
37
|
Jeweler::GemcutterTasks.new
|
21
|
-
rescue LoadError
|
22
|
-
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
23
38
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.7
|
@@ -5,7 +5,8 @@ require 'logger'
|
|
5
5
|
class MigratorTasks < ::Rake::TaskLib
|
6
6
|
DefaultEnv = 'development'
|
7
7
|
|
8
|
-
attr_accessor :name, :base, :vendor, :config, :schema, :env, :current_env
|
8
|
+
attr_accessor :name, :base, :vendor, :config, :schema, :env, :current_env
|
9
|
+
attr_accessor :verbose, :log_level, :logger, :sub_namespace
|
9
10
|
attr_reader :migrations
|
10
11
|
|
11
12
|
def initialize(name = :migrator)
|
@@ -32,266 +33,279 @@ class MigratorTasks < ::Rake::TaskLib
|
|
32
33
|
|
33
34
|
def define
|
34
35
|
namespace :db do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if @config.is_a?(Hash)
|
40
|
-
ActiveRecord::Base.configurations = @config
|
41
|
-
else
|
42
|
-
require 'erb'
|
43
|
-
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(@config)).result)
|
36
|
+
if sub_namespace
|
37
|
+
namespace sub_namespace do
|
38
|
+
define_tasks
|
44
39
|
end
|
45
|
-
|
46
|
-
|
47
|
-
logger = @logger
|
48
|
-
else
|
49
|
-
logger = Logger.new($stderr)
|
50
|
-
logger.level = @log_level
|
51
|
-
end
|
52
|
-
ActiveRecord::Base.logger = logger
|
40
|
+
else
|
41
|
+
define_tasks
|
53
42
|
end
|
43
|
+
end
|
44
|
+
end
|
54
45
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
46
|
+
def define_tasks
|
47
|
+
sub_namespace_with_separator = sub_namespace ? "#{sub_namespace}:" : ''
|
58
48
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
49
|
+
def ar_init(connect = true)
|
50
|
+
require 'active_record'
|
51
|
+
self.current_env = ENV[@env] || DefaultEnv
|
52
|
+
|
53
|
+
if @config.is_a?(Hash)
|
54
|
+
ActiveRecord::Base.configurations = @config
|
55
|
+
else
|
56
|
+
require 'erb'
|
57
|
+
ActiveRecord::Base.configurations = YAML::load(ERB.new(IO.read(@config)).result)
|
67
58
|
end
|
59
|
+
ActiveRecord::Base.establish_connection(current_env) if connect
|
60
|
+
if @logger
|
61
|
+
logger = @logger
|
62
|
+
else
|
63
|
+
logger = Logger.new($stderr)
|
64
|
+
logger.level = @log_level
|
65
|
+
end
|
66
|
+
ActiveRecord::Base.logger = logger
|
67
|
+
end
|
68
|
+
|
69
|
+
task :ar_init do
|
70
|
+
ar_init
|
71
|
+
end
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
73
|
+
desc "Migrate the database using the scripts in the migrations directory. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
|
74
|
+
task :migrate => :ar_init do
|
75
|
+
require "#{@vendor}/migration_helpers/init"
|
76
|
+
ActiveRecord::Migration.verbose = ENV['VERBOSE'] || @verbose
|
77
|
+
@migrations.each do |path|
|
78
|
+
ActiveRecord::Migrator.migrate(path, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
|
72
79
|
end
|
80
|
+
Rake::Task["db:#{sub_namespace_with_separator}schema:dump"].execute
|
81
|
+
end
|
73
82
|
|
83
|
+
desc "Retrieves the current schema version number"
|
84
|
+
task :version => :ar_init do
|
85
|
+
puts "Current version: #{ActiveRecord::Migrator.current_version}"
|
86
|
+
end
|
74
87
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
begin
|
82
|
-
# Create the SQLite database
|
83
|
-
ActiveRecord::Base.establish_connection(config)
|
84
|
-
ActiveRecord::Base.connection
|
85
|
-
rescue Exception => e
|
86
|
-
$stderr.puts e, *(e.backtrace)
|
87
|
-
$stderr.puts "Couldn't create database for #{config.inspect}"
|
88
|
-
end
|
89
|
-
end
|
90
|
-
return # Skip the else clause of begin/rescue
|
88
|
+
|
89
|
+
def create_database(config)
|
90
|
+
begin
|
91
|
+
if config['adapter'] =~ /sqlite/
|
92
|
+
if File.exist?(config['database'])
|
93
|
+
$stderr.puts "#{config['database']} already exists"
|
91
94
|
else
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
|
101
|
-
error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
|
102
|
-
access_denied_error = 1045
|
103
|
-
begin
|
104
|
-
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
105
|
-
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
106
|
-
ActiveRecord::Base.establish_connection(config)
|
107
|
-
rescue error_class => sqlerr
|
108
|
-
if sqlerr.errno == access_denied_error
|
109
|
-
print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>"
|
110
|
-
root_password = $stdin.gets.strip
|
111
|
-
grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \
|
112
|
-
"TO '#{config['username']}'@'localhost' " \
|
113
|
-
"IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;"
|
114
|
-
ActiveRecord::Base.establish_connection(config.merge(
|
115
|
-
'database' => nil, 'username' => 'root', 'password' => root_password))
|
116
|
-
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
117
|
-
ActiveRecord::Base.connection.execute grant_statement
|
118
|
-
ActiveRecord::Base.establish_connection(config)
|
119
|
-
else
|
120
|
-
$stderr.puts sqlerr.error
|
121
|
-
$stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}"
|
122
|
-
$stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset']
|
123
|
-
end
|
124
|
-
end
|
125
|
-
when 'postgresql'
|
126
|
-
@encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
|
127
|
-
begin
|
128
|
-
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
129
|
-
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
|
130
|
-
ActiveRecord::Base.establish_connection(config)
|
131
|
-
rescue Exception => e
|
132
|
-
$stderr.puts e, *(e.backtrace)
|
133
|
-
$stderr.puts "Couldn't create database for #{config.inspect}"
|
134
|
-
end
|
95
|
+
begin
|
96
|
+
# Create the SQLite database
|
97
|
+
ActiveRecord::Base.establish_connection(config)
|
98
|
+
ActiveRecord::Base.connection
|
99
|
+
rescue Exception => e
|
100
|
+
$stderr.puts e, *(e.backtrace)
|
101
|
+
$stderr.puts "Couldn't create database for #{config.inspect}"
|
102
|
+
end
|
135
103
|
end
|
104
|
+
return # Skip the else clause of begin/rescue
|
136
105
|
else
|
137
|
-
|
106
|
+
ActiveRecord::Base.establish_connection(config)
|
107
|
+
ActiveRecord::Base.connection
|
138
108
|
end
|
139
|
-
|
140
|
-
|
141
|
-
desc 'Create the database from config/database.yml for the current DATABASE_ENV'
|
142
|
-
task :create do
|
143
|
-
ar_init(false)
|
144
|
-
config = ActiveRecord::Base.configurations[self.current_env]
|
145
|
-
create_database config
|
146
|
-
end
|
147
|
-
|
148
|
-
def drop_database(config)
|
109
|
+
rescue
|
149
110
|
case config['adapter']
|
150
111
|
when /mysql/
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
112
|
+
@charset = ENV['CHARSET'] || 'utf8'
|
113
|
+
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
|
114
|
+
creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
|
115
|
+
error_class = config['adapter'] =~ /mysql2/ ? Mysql2::Error : Mysql::Error
|
116
|
+
access_denied_error = 1045
|
117
|
+
begin
|
118
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
119
|
+
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
120
|
+
ActiveRecord::Base.establish_connection(config)
|
121
|
+
rescue error_class => sqlerr
|
122
|
+
if sqlerr.errno == access_denied_error
|
123
|
+
print "#{sqlerr.error}. \nPlease provide the root password for your mysql installation\n>"
|
124
|
+
root_password = $stdin.gets.strip
|
125
|
+
grant_statement = "GRANT ALL PRIVILEGES ON #{config['database']}.* " \
|
126
|
+
"TO '#{config['username']}'@'localhost' " \
|
127
|
+
"IDENTIFIED BY '#{config['password']}' WITH GRANT OPTION;"
|
128
|
+
ActiveRecord::Base.establish_connection(config.merge(
|
129
|
+
'database' => nil, 'username' => 'root', 'password' => root_password))
|
130
|
+
ActiveRecord::Base.connection.create_database(config['database'], creation_options)
|
131
|
+
ActiveRecord::Base.connection.execute grant_statement
|
132
|
+
ActiveRecord::Base.establish_connection(config)
|
133
|
+
else
|
134
|
+
$stderr.puts sqlerr.error
|
135
|
+
$stderr.puts "Couldn't create database for #{config.inspect}, charset: #{config['charset'] || @charset}, collation: #{config['collation'] || @collation}"
|
136
|
+
$stderr.puts "(if you set the charset manually, make sure you have a matching collation)" if config['charset']
|
137
|
+
end
|
138
|
+
end
|
158
139
|
when 'postgresql'
|
159
|
-
|
160
|
-
|
140
|
+
@encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
|
141
|
+
begin
|
142
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
143
|
+
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding))
|
144
|
+
ActiveRecord::Base.establish_connection(config)
|
145
|
+
rescue Exception => e
|
146
|
+
$stderr.puts e, *(e.backtrace)
|
147
|
+
$stderr.puts "Couldn't create database for #{config.inspect}"
|
148
|
+
end
|
161
149
|
end
|
150
|
+
else
|
151
|
+
$stderr.puts "#{config['database']} already exists" unless config['adapter'] =~ /sqlite/
|
162
152
|
end
|
153
|
+
end
|
154
|
+
|
155
|
+
desc 'Create the database from config/database.yml for the current DATABASE_ENV'
|
156
|
+
task :create do
|
157
|
+
ar_init(false)
|
158
|
+
config = ActiveRecord::Base.configurations[self.current_env]
|
159
|
+
create_database config
|
160
|
+
end
|
163
161
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
162
|
+
def drop_database(config)
|
163
|
+
case config['adapter']
|
164
|
+
when /mysql/
|
165
|
+
ActiveRecord::Base.establish_connection(config)
|
166
|
+
ActiveRecord::Base.connection.drop_database config['database']
|
167
|
+
when /^sqlite/
|
168
|
+
require 'pathname'
|
169
|
+
path = Pathname.new(config['database'])
|
170
|
+
file = path.absolute? ? path.to_s : File.join(@base, path)
|
171
|
+
FileUtils.rm(file)
|
172
|
+
when 'postgresql'
|
173
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
174
|
+
ActiveRecord::Base.connection.drop_database config['database']
|
168
175
|
end
|
176
|
+
end
|
177
|
+
|
178
|
+
desc 'Drops the database for the current DATABASE_ENV'
|
179
|
+
task :drop => :ar_init do
|
180
|
+
config = ActiveRecord::Base.configurations[current_env]
|
181
|
+
drop_database(config)
|
182
|
+
end
|
169
183
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
end
|
184
|
+
namespace :migrate do
|
185
|
+
[:up, :down].each do |direction|
|
186
|
+
desc "Runs the '#{direction}' for a given migration VERSION."
|
187
|
+
task direction => :ar_init do
|
188
|
+
ActiveRecord::Migration.verbose = @verbose
|
189
|
+
version = ENV["VERSION"].to_i
|
190
|
+
raise "VERSION is required (must be a number)" if version == 0
|
191
|
+
migration_path = nil
|
192
|
+
if @migrations.length == 1
|
193
|
+
migration_path = @migrations.first
|
194
|
+
else
|
195
|
+
@migrations.each do |path|
|
196
|
+
Dir[File.join(path, '*.rb')].each do |file|
|
197
|
+
if File.basename(file).match(/^\d+/)[0] == version.to_s
|
198
|
+
migration_path = path
|
199
|
+
break
|
187
200
|
end
|
188
201
|
end
|
189
|
-
raise "Migration #{version} wasn't found on paths #{@migrations.join(', ')}" if migration_path.nil?
|
190
202
|
end
|
191
|
-
|
192
|
-
Rake::Task["db:schema:dump"].execute
|
203
|
+
raise "Migration #{version} wasn't found on paths #{@migrations.join(', ')}" if migration_path.nil?
|
193
204
|
end
|
205
|
+
ActiveRecord::Migrator.run(direction, migration_path, version)
|
206
|
+
Rake::Task["db:#{sub_namespace_with_separator}schema:dump"].execute
|
194
207
|
end
|
195
208
|
end
|
209
|
+
end
|
196
210
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
211
|
+
desc "Raises an error if there are pending migrations"
|
212
|
+
task :abort_if_pending_migrations => :ar_init do
|
213
|
+
@migrations.each do |path|
|
214
|
+
pending_migrations = ActiveRecord::Migrator.new(:up, path).pending_migrations
|
201
215
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
end
|
207
|
-
abort %{Run "rake db:migrate" to update your database then try again.}
|
216
|
+
if pending_migrations.any?
|
217
|
+
puts "You have #{pending_migrations.size} pending migrations:"
|
218
|
+
pending_migrations.each do |pending_migration|
|
219
|
+
puts ' %4d %s' % [pending_migration.version, pending_migration.name]
|
208
220
|
end
|
221
|
+
abort %{Run "rake db:migrate" to update your database then try again.}
|
209
222
|
end
|
210
223
|
end
|
224
|
+
end
|
211
225
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
end
|
226
|
+
namespace :schema do
|
227
|
+
desc "Create schema.rb file that can be portably used against any DB supported by AR"
|
228
|
+
task :dump => :ar_init do
|
229
|
+
if schema_file = ENV['SCHEMA'] || @schema
|
230
|
+
require 'active_record/schema_dumper'
|
231
|
+
File.open(schema_file, "w") do |file|
|
232
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
220
233
|
end
|
221
234
|
end
|
235
|
+
end
|
222
236
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end
|
237
|
+
desc "Load a ar_schema.rb file into the database"
|
238
|
+
task :load => :ar_init do
|
239
|
+
file = ENV['SCHEMA'] || @schema
|
240
|
+
load(file)
|
228
241
|
end
|
242
|
+
end
|
229
243
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
244
|
+
namespace :test do
|
245
|
+
desc "Recreate the test database from the current schema.rb"
|
246
|
+
task :load => ["db:#{sub_namespace_with_separator}ar_init", "db:#{sub_namespace_with_separator}test:purge"] do
|
247
|
+
ActiveRecord::Base.establish_connection(:test)
|
248
|
+
ActiveRecord::Schema.verbose = false
|
249
|
+
Rake::Task["db:#{sub_namespace_with_separator}schema:load"].invoke
|
250
|
+
end
|
237
251
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
end
|
252
|
+
desc "Empty the test database"
|
253
|
+
task :purge => "db:#{sub_namespace_with_separator}ar_init" do
|
254
|
+
config = ActiveRecord::Base.configurations['test']
|
255
|
+
case config["adapter"]
|
256
|
+
when "mysql"
|
257
|
+
ActiveRecord::Base.establish_connection(:test)
|
258
|
+
ActiveRecord::Base.connection.recreate_database(config["database"], config)
|
259
|
+
when "postgresql" #TODO i doubt this will work <-> methods are not defined
|
260
|
+
ActiveRecord::Base.clear_active_connections!
|
261
|
+
drop_database(config)
|
262
|
+
create_database(config)
|
263
|
+
when "sqlite", "sqlite3"
|
264
|
+
db_file = config["database"] || config["dbfile"]
|
265
|
+
File.delete(db_file) if File.exist?(db_file)
|
266
|
+
when "sqlserver"
|
267
|
+
drop_script = "#{config["host"]}.#{config["database"]}.DP1".gsub(/\\/, '-')
|
268
|
+
`osql -E -S #{config["host"]} -d #{config["database"]} -i db\\#{drop_script}`
|
269
|
+
`osql -E -S #{config["host"]} -d #{config["database"]} -i db\\test_structure.sql`
|
270
|
+
when "oci", "oracle"
|
271
|
+
ActiveRecord::Base.establish_connection(:test)
|
272
|
+
ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
|
273
|
+
ActiveRecord::Base.connection.execute(ddl)
|
274
|
+
end
|
275
|
+
when "firebird"
|
276
|
+
ActiveRecord::Base.establish_connection(:test)
|
277
|
+
ActiveRecord::Base.connection.recreate_database!
|
278
|
+
else
|
279
|
+
raise "Task not supported by #{config["adapter"].inspect}"
|
267
280
|
end
|
268
|
-
|
269
|
-
desc 'Check for pending migrations and load the test schema'
|
270
|
-
task :prepare => ['db:abort_if_pending_migrations', 'db:test:load']
|
271
281
|
end
|
272
282
|
|
273
|
-
desc '
|
274
|
-
task :
|
275
|
-
|
283
|
+
desc 'Check for pending migrations and load the test schema'
|
284
|
+
task :prepare => ["db:#{sub_namespace_with_separator}abort_if_pending_migrations", "db:#{sub_namespace_with_separator}test:load"]
|
285
|
+
end
|
276
286
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
287
|
+
desc 'generate a model=name field="field1:type field2:type"'
|
288
|
+
task :generate do
|
289
|
+
ts = Time.now.strftime '%Y%m%d%H%%M%S'
|
290
|
+
|
291
|
+
if ENV['model']
|
292
|
+
table_name = ENV['model']
|
293
|
+
else
|
294
|
+
print 'model name> '
|
295
|
+
table_name = $stdin.gets.strip
|
296
|
+
end
|
283
297
|
|
284
|
-
|
298
|
+
raise ArgumentError, 'must provide a name for the model to generate' if table_name.empty?
|
285
299
|
|
286
|
-
|
300
|
+
create_table_str = "create_table :#{table_name} do |t|"
|
287
301
|
|
288
|
-
|
302
|
+
fields = ENV['fields'] if ENV['fields']
|
289
303
|
|
290
|
-
|
304
|
+
columns = ENV.has_key?('fields') ? ENV['fields'].split.map { |v| "t.#{v.sub(/:/, ' :')}" }.join("\n#{' '*6}") : nil
|
291
305
|
|
292
|
-
|
306
|
+
create_table_str << "\n #{columns}" if columns
|
293
307
|
|
294
|
-
|
308
|
+
contents = <<-MIGRATION
|
295
309
|
class Create#{class_name table_name} < ActiveRecord::Migration
|
296
310
|
def self.up
|
297
311
|
#{create_table_str}
|
@@ -305,18 +319,18 @@ class Create#{class_name table_name} < ActiveRecord::Migration
|
|
305
319
|
end
|
306
320
|
MIGRATION
|
307
321
|
|
308
|
-
|
309
|
-
|
322
|
+
create_file @migrations.first, file_name("create_#{table_name}"), contents
|
323
|
+
end
|
310
324
|
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
325
|
+
desc "Create a new migration"
|
326
|
+
task :new_migration do |t|
|
327
|
+
unless migration = ENV['name']
|
328
|
+
puts "Error: must provide name of migration to generate."
|
329
|
+
puts "For example: rake #{t.name} name=add_field_to_form"
|
330
|
+
abort
|
331
|
+
end
|
318
332
|
|
319
|
-
|
333
|
+
file_contents = <<eof
|
320
334
|
class #{class_name migration} < ActiveRecord::Migration
|
321
335
|
def self.up
|
322
336
|
end
|
@@ -327,10 +341,9 @@ class #{class_name migration} < ActiveRecord::Migration
|
|
327
341
|
end
|
328
342
|
eof
|
329
343
|
|
330
|
-
|
344
|
+
create_file @migrations.first, file_name(migration), file_contents
|
331
345
|
|
332
|
-
|
333
|
-
end
|
346
|
+
puts "Created migration #{file_name migration}"
|
334
347
|
end
|
335
348
|
end
|
336
349
|
|
@@ -28,8 +28,9 @@ describe 'Standalone migrations' do
|
|
28
28
|
`cd spec/tmp && #{cmd} 2>&1`
|
29
29
|
end
|
30
30
|
|
31
|
-
def make_migration(name)
|
32
|
-
|
31
|
+
def make_migration(name, options={})
|
32
|
+
task_name = options[:task_name] || 'db:new_migration'
|
33
|
+
migration = run("rake #{task_name} name=#{name}").match(%r{db/migrations/\d+.*.rb})[0]
|
33
34
|
content = read(migration)
|
34
35
|
content.sub!(/def self.down.*?\send/m, "def self.down;puts 'DOWN-#{name}';end")
|
35
36
|
content.sub!(/def self.up.*?\send/m, "def self.up;puts 'UP-#{name}';end")
|
@@ -37,6 +38,11 @@ describe 'Standalone migrations' do
|
|
37
38
|
migration.match(/\d{14}/)[0]
|
38
39
|
end
|
39
40
|
|
41
|
+
def make_sub_namespaced_migration(namespace, name)
|
42
|
+
# specify complete task name here to avoid conditionals in make_migration
|
43
|
+
make_migration(name, :task_name => "db:#{namespace}:new_migration")
|
44
|
+
end
|
45
|
+
|
40
46
|
def write_rakefile(config=nil)
|
41
47
|
write 'Rakefile', <<-TXT
|
42
48
|
$LOAD_PATH.unshift '#{File.expand_path('lib')}'
|
@@ -119,6 +125,24 @@ end
|
|
119
125
|
run("rake db:new_migration name=test_abc").should =~ %r{Created migration .*db/migrations/\d+_test_abc\.rb}
|
120
126
|
end
|
121
127
|
end
|
128
|
+
|
129
|
+
context 'sub-namespaced task' do
|
130
|
+
before do
|
131
|
+
write_rakefile %{t.sub_namespace = "widgets"}
|
132
|
+
end
|
133
|
+
it "fails if i do not add a name" do
|
134
|
+
run("rake db:widgets:new_migration").should_not =~ /SUCCESS/
|
135
|
+
end
|
136
|
+
|
137
|
+
it "generates a new migration with this name and timestamp" do
|
138
|
+
run("rake db:widgets:new_migration name=test_widget").should =~ %r{Created migration .*spec/tmp/db/migrations/\d+_test_widget\.rb}
|
139
|
+
run("ls db/migrations").should =~ /^\d+_test_widget.rb$/
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'does not create top level db:new_migration task' do
|
143
|
+
run('rake db:new_migration').should =~ /Don't know how to build task 'db:new_migration'/
|
144
|
+
end
|
145
|
+
end
|
122
146
|
end
|
123
147
|
|
124
148
|
describe 'db:version' do
|
@@ -151,6 +175,22 @@ end
|
|
151
175
|
result.should =~ /Migrating to CreateTests2 \(2010/
|
152
176
|
end
|
153
177
|
end
|
178
|
+
|
179
|
+
context 'sub-namespaced task' do
|
180
|
+
before do
|
181
|
+
write_rakefile %{t.sub_namespace = "widgets"}
|
182
|
+
end
|
183
|
+
it 'runs the migrations' do
|
184
|
+
run("rake db:widgets:new_migration name=new_widget")
|
185
|
+
result = run("rake db:widgets:migrate")
|
186
|
+
result.should =~ /SUCCESS/
|
187
|
+
result.should =~ /Migrating to NewWidget \(#{Time.now.year}/
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'does not create top level db:new_migration task' do
|
191
|
+
run('rake db:migrate').should =~ /Don't know how to build task 'db:migrate'/
|
192
|
+
end
|
193
|
+
end
|
154
194
|
end
|
155
195
|
|
156
196
|
describe 'db:migrate:down' do
|
@@ -193,6 +233,23 @@ end
|
|
193
233
|
result.should =~ /wasn't found on path/
|
194
234
|
end
|
195
235
|
end
|
236
|
+
|
237
|
+
context 'sub-namespaced task' do
|
238
|
+
before do
|
239
|
+
write_rakefile %{t.sub_namespace = "widgets"}
|
240
|
+
end
|
241
|
+
it 'migrates down' do
|
242
|
+
make_sub_namespaced_migration('widgets', 'widget_xxx')
|
243
|
+
sleep 1
|
244
|
+
version = make_sub_namespaced_migration('widgets', 'widget_yyy')
|
245
|
+
run 'rake db:widgets:migrate'
|
246
|
+
|
247
|
+
result = run("rake db:widgets:migrate:down VERSION=#{version}")
|
248
|
+
result.should =~ /SUCCESS/
|
249
|
+
result.should_not =~ /DOWN-widget_xxx/
|
250
|
+
result.should =~ /DOWN-widget_yyy/
|
251
|
+
end
|
252
|
+
end
|
196
253
|
end
|
197
254
|
|
198
255
|
describe 'db:migrate:up' do
|
@@ -232,6 +289,22 @@ end
|
|
232
289
|
result.should =~ /wasn't found on path/
|
233
290
|
end
|
234
291
|
end
|
292
|
+
|
293
|
+
context 'sub-namespaced task' do
|
294
|
+
before do
|
295
|
+
write_rakefile %{t.sub_namespace = "widgets"}
|
296
|
+
end
|
297
|
+
it 'migrates up' do
|
298
|
+
make_sub_namespaced_migration('widgets', 'widget_xxx')
|
299
|
+
run 'rake db:widgets:migrate'
|
300
|
+
sleep 1
|
301
|
+
version = make_sub_namespaced_migration('widgets', 'widget_yyy')
|
302
|
+
result = run("rake db:widgets:migrate:up VERSION=#{version}")
|
303
|
+
result.should =~ /SUCCESS/
|
304
|
+
result.should_not =~ /UP-widget_xxx/
|
305
|
+
result.should =~ /UP-widget_yyy/
|
306
|
+
end
|
307
|
+
end
|
235
308
|
end
|
236
309
|
|
237
310
|
describe 'schema:dump' do
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{standalone_migrations}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Todd Huss", "Michael Grosser"]
|
12
|
-
s.date = %q{2011-04-
|
12
|
+
s.date = %q{2011-04-19}
|
13
13
|
s.email = %q{thuss@gabrito.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"README.markdown"
|
@@ -28,13 +28,14 @@ Gem::Specification.new do |s|
|
|
28
28
|
]
|
29
29
|
s.homepage = %q{http://github.com/thuss/standalone-migrations}
|
30
30
|
s.require_paths = ["lib"]
|
31
|
-
s.rubygems_version = %q{1.
|
31
|
+
s.rubygems_version = %q{1.3.7}
|
32
32
|
s.summary = %q{A thin wrapper to use Rails Migrations in non Rails projects}
|
33
33
|
s.test_files = [
|
34
34
|
"spec/standalone_migrations_spec.rb"
|
35
35
|
]
|
36
36
|
|
37
37
|
if s.respond_to? :specification_version then
|
38
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
38
39
|
s.specification_version = 3
|
39
40
|
|
40
41
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
metadata
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standalone_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 4
|
8
|
+
- 7
|
9
|
+
version: 0.4.7
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
12
|
- Todd Huss
|
@@ -11,7 +15,7 @@ autorequire:
|
|
11
15
|
bindir: bin
|
12
16
|
cert_chain: []
|
13
17
|
|
14
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-19 00:00:00 -07:00
|
15
19
|
default_executable:
|
16
20
|
dependencies:
|
17
21
|
- !ruby/object:Gem::Dependency
|
@@ -22,6 +26,8 @@ dependencies:
|
|
22
26
|
requirements:
|
23
27
|
- - ">="
|
24
28
|
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 0
|
25
31
|
version: "0"
|
26
32
|
type: :runtime
|
27
33
|
version_requirements: *id001
|
@@ -33,6 +39,8 @@ dependencies:
|
|
33
39
|
requirements:
|
34
40
|
- - ">="
|
35
41
|
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
36
44
|
version: "0"
|
37
45
|
type: :runtime
|
38
46
|
version_requirements: *id002
|
@@ -69,17 +77,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
77
|
requirements:
|
70
78
|
- - ">="
|
71
79
|
- !ruby/object:Gem::Version
|
80
|
+
segments:
|
81
|
+
- 0
|
72
82
|
version: "0"
|
73
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
84
|
none: false
|
75
85
|
requirements:
|
76
86
|
- - ">="
|
77
87
|
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 0
|
78
90
|
version: "0"
|
79
91
|
requirements: []
|
80
92
|
|
81
93
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.
|
94
|
+
rubygems_version: 1.3.7
|
83
95
|
signing_key:
|
84
96
|
specification_version: 3
|
85
97
|
summary: A thin wrapper to use Rails Migrations in non Rails projects
|