Использование config.after_initialize
работает, но есть две проблемы:
он запускается после всех других инициализаторов, поэтому, если эти инициализаторы выполняют какие-то операции с базами данных, они будут использовать старую схему
он работает во всех средах, включая задачи Rake и работников Resque. Мы не хотим автоматически мигрировать каждый раз, когда запускаем rake routes
, не так ли? И мы не хотим, чтобы множественные миграции происходили одновременно.
Мое решение состоит в том, чтобы использовать файл config/initializers
, чтобы я мог решить, в каком порядке он запускается, и проверить, не находимся ли мы в грабли.
Кроме того, до тех пор, пока я не освою автоматическую миграцию при развертывании, я делаю это только в средах development
и test
.
Наконец, я хочу напечатать некоторую дополнительную информацию (переход на версию и обратно), поэтому вместо однострочного я получаю доступ к Мигратору, возможно, более тесно, чем следовало бы.
Ах да! Также следует написать schema.rb
. Так что я нагло краду код из db:schema:dump
изнутри active_record/railties/databases.rake
. (Разве не было бы неплохо, если бы грабли были методами объекта, поэтому мы могли бы просто вызывать их?)
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
Обновление: очевидно, новая версия Rake более либеральна при загрузке, поэтому выражение !defined?(Rake)
всегда ложно, даже если оно запускается из командной строки (т.е. не внутри Rake Task или Resque Worker). Вместо этого я пробую следующее
caller.grep(/rake/).empty?