Is there a plugin available to have Rails run through a db:migrate on startup? I'm looking for a solution that doesn't involve calling out to the Rake task via the shell; so, no "system('rake db:migrate')
".
I can readily write my own plugin to do this, but figured it would be better to use/improve an existing migrate-on-init plugin if one exists.
Using config.after_initialize
works, but there are two problems:
it runs after all other initializers, so if those initializers do some databasey stuff they'd be using the old schema
it runs in all environments, including Rake tasks and Resque workers. We don't want to automatically migrate every time we run rake routes
, do we? And we don't want multiple migrations to happen simultaneously.
My solution is to use a config/initializers
file, so I can decide what order it runs in, and to check for whether we're inside a rake task.
Also, until I'm comfortable with auto-migrate on deploy, I'm only doing this in the development
and test
environments.
Finally, I want to print some extra information (migrating to and from version), so instead of a one-liner, I reach into the Migrator, perhaps more intimately than I should.
Oh yeah! Also it should write schema.rb
. So I'm blatantly stealing code from db:schema:dump
from inside active_record/railties/databases.rake
. (Wouldn't it be nice if rake tasks were methods on an object, so we could just call them?)
config/initializers/automatically_migrate.rb
:
# don't do this in production
if (Rails.env.development? or Rails.env.test?) and
# don't do this in a worker or task
!defined?(Rake) # SEE BELOW FOR POSSIBLE FIX
migrations_paths = ActiveRecord::Migrator.migrations_paths
migrator = ActiveRecord::Migrator.new(:up, migrations_paths, nil)
pending_migrations = migrator.pending_migrations
unless pending_migrations.empty?
puts "Migrating from #{migrator.current_version} to #{pending_migrations.last.version}"
migrator.migrate
require 'active_record/schema_dumper'
filename = ENV['SCHEMA'] || "#{Rails.root}/db/schema.rb"
File.open(filename, "w:utf-8") do |file|
ActiveRecord::Base.establish_connection(Rails.env)
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
end
end
Update: Apparently the new version of Rake is more liberal about when it loads, so the expression !defined?(Rake)
is always false, even when being run from the command line (i.e. not inside a Rake Task or a Resque Worker). I'm trying the following instead
caller.grep(/rake/).empty?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With