Rails: How to create migration in subdirectory with Rails?
Task rake db:migrate
has a hard coded path to migrations. But you can create your own rake task. For example, create lib/tasks/custom_db_migrate.rake
with the following contents:
namespace :db do
task :custom_migrate => :environment do
ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
ActiveRecord::Migrator.migrate("db/migrate/custom", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
end
end
Now you can run rake db:custom_migrate
to run migrations which are located in db/migrate/custom
. But it will not use migrations from the default path.
You might want to read the source code for the ActiveRecord migrations.
If you're using Sinatra and building your own rake task, you can do the following:
require './app'
require 'sinatra/activerecord/rake'
ActiveRecord::Migrator.migrations_paths = 'your/path/goes/here'
When you run rake -T
, you'll get the db namespace:
rake db:create_migration # create an ActiveRecord migration
rake db:migrate # migrate the database (use version with VERSION=n)
rake db:rollback # roll back the migration (use steps with STEP=n)
@Vasily thank's for your response. After reading it and couple more questions from stackoverflow I came up with this solution:
Since I write my own generator to create user tables I included Rails::Generators::Migration in it so I can override next_migration_number method like this:
def self.next_migration_number(dirname)
if ActiveRecord::Base.timestamped_migrations
Time.now.utc.strftime("custom/%Y%m%d%H%M%S")
else
"custom/%.3d" % (current_migration_number(dirname) + 1)
end
end
Now all migrations generated by user are created in db/migrations/custom directory.
Then I wrote normal rails migration that executes all migrations from db/migrations/custom directory:
class ExecuteCustomMigrations < ActiveRecord::Migration
MIGRATIONS_PATH='db/migrate/custom'
def self.up
Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].
sort.map{|filename|require filename}.flatten.
each{|class_name| const_get(class_name).up}
end
def self.down
Dir["#{MIGRATIONS_PATH}/[0-9]*_*.rb"].sort.reverse.
map{|filename|require filename}.flatten.
each{|class_name| const_get(class_name).down}
end
end
After user creates custom table i call this migration with this code:
Rake::Task["db:migrate:redo"].execute("VERSION=20110108213453")