standalone_migrations 0.4.5 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.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
|