This project is archived and is in readonly mode.
rake db:migrate doesn't detect new migration
-
Tom Ward
- Tag changed from activerecord, migration to activerecord, migration
Rollo,
Could you tell me what OS/Database/Version of Ruby you are using? It will help in trying to recreate the issue.
Tom
-
Tom Ward
According to http://stackoverflow.com/questio... it appears this may be caused by a VERSION environment variable already being set.
-
Jean
@Tom : as I explain in the stackoverflow post this is still an error.
The problem
at least on windows, and most likely on *nix envs too, when the environment already has a VERSION variable set (and on windows it is case insensitive so Version brings it up too) and VERSION contains some arbitrary string which does not map to an integer, the rake db:migrate command's behaviour is erroneous.
running it once on an empty database will migrate up, but then running that same command again to solve pending migrations will actually revert the database instead of upgrading it.
main incriminated files :
database.rake
@@@ruby desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x. Turn off output with VERBOSE=false." task :migrate => :environment do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil) Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby end
### migration.rb in active records library @@@ruby class Migrator#:nodoc: class << self def migrate(migrations_path, target_version = nil) case when target_version.nil? then up(migrations_path, target_version) when current_version > target_version then down(migrations_path, target_version) else up(migrations_path, target_version) end endthe bug is in this line @@@ruby ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
ENV["VERSION"].to_i will return 0 if ENV["VERSION"] is not a valid integer (ruby behaviour). Thus if for some reason the user has a version variable set, it will behave erratically. # Solutions # ## The minimal solution ## Is to fail loudly when VERSION is not an integer, so that at least the user knows what is wrong and doesn't loose data. for this the code should be changed to be @@@ruby ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? Integer.new(ENV["VERSION"]) : nil)A slightly better solution
at least check that the VERSION is a valid timestamp with respect to the YYYYMMDD format instead of checking for an integer (there may be backward compatibility reasons why you wouldn't want to do that)
Improved solution
Actually list the content of the migration directory and ensure that the VERSION is valid for the files in that directory.
The correct solution
Do not use environment variables to store program argument ... this is just wrong and you can not make any assumptions as to the existing or non existing environment variables.
-
Frederick Cheung
- State changed from new to duplicate
Duplicate of #1203 [PATCH] When environment variable "VERSION" exists, db:migration will fail. (created later, but has patches)