Ruby on Railsのdb:migrateの挙動
Ruby on Railsの2.1.1でうりゃうりゃと適当なアプリを作ろうとしたら、いきなりdb:migrateでつまづいた。(たぶん)特別なことをしている訳ではないのだが、以下のような形。
D:\rails>rails exampleapp create create app/controllers create app/helpers ... 略 ... create log/production.log create log/development.log create log/test.log D:\rails>cd exampleapp D:\rails\exampleapp>ruby ./script/generate migration user create db/migrate create db/migrate/20081011183401_user.rb D:\rails\exampleapp>rake db:migrate (in D:/rails/exampleapp) rake aborted! No migration with version number 2 (See full trace by running task with --trace)
何故か初回なのにVERSION=2で実行されてエラーになっている。
scaffoldで作った場合も同様。
VERSION=0を明示的に指定してdb:migrateを実行した場合は一応動く。
英語のGoogle先生に聞いてみてもあまり事例が出てこないし回答も出ていない。
じゃあ、エラーメッセージ通りトレースしてみるかいということで実行した結果が以下。
D:\rails\exampleapp>rake db:migrate --trace (in D:/rails/exampleapp) ** Invoke db:migrate (first_time) ** Invoke environment (first_time) ** Execute environment ** Execute db:migrate rake aborted! No migration with version number 2 D:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/migration.rb:435:in `migrate' D:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/migration.rb:373:in `up' D:/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/migration.rb:358:in `migrate' D:/Ruby/lib/ruby/gems/1.8/gems/rails-2.1.1/lib/tasks/databases.rake:99 D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `call' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:617:in `execute' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `each' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:612:in `execute' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:578:in `invoke_with_call_chain' D:/Ruby/lib/ruby/1.8/monitor.rb:242:in `synchronize' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:571:in `invoke_with_call_chain' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:564:in `invoke' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2019:in `invoke_task' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `each' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1997:in `top_level' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1991:in `top_level' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1970:in `run' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:2036:in `standard_exception_handling' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/lib/rake.rb:1967:in `run' D:/Ruby/lib/ruby/gems/1.8/gems/rake-0.8.3/bin/rake:31 D:/Ruby/bin/rake:19:in `load' D:/Ruby/bin/rake:19
activerecord-2.1.1/libactive_record/migration.rbに入ってきた時点で既にmigrateの引数に「2」が入っている。
active_record先生はtargetのバージョンを「2」でmigrateしようとするが、当然そんなバージョンはないので怒られるのである。
呼び出し元のrails-2.1.1/lib/tasks/databases.rakeをみたら以下のような感じ。
ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
直前で環境変数VERSIONとto_iの結果を表示してみたら、"2.0.37"と"2"と表示された。
"."付の値をto_iして意図的に情報劣化させるというのはありえない感じがするので、"2.0.37"という値自体が正しくない気がする。
この値はどこで設定しているのだろうと思って呼び出し元ファイルで"VERSION"を検索してみたがどこにもない。
「じゃあ、ここスか」ということでOSの環境変数VERSIONをみたらバッチリ"2.0.37"と書いてあった。
そもそもこの環境変数自体の由来がよく分からないが、Rails先生が想定しているのはrake-0.8.3/lib/rake.rbでガシガシと環境変数に設定している「rake」コマンドのオプションの方だろう。
エラーの原因が分かったのでD:\Ruby\bin\rake.batのはじめの方にエイヤと以下の行を追加して実行してみる。
set VERSION=
無事成功。
D:\rails\exampleapp>rake db:migrate (in D:/rails/exampleapp) == 20081011183401 User: migrating ============================================= == 20081011183401 User: migrated (0.0000s) ====================================
この件に関して質問や情報がぜんぜん見つからないのだけれど、他の人では発生しないのだろうか。ひとまず以下のソース履歴を覗いてみたら2005年の時点で既にENV["VERSION"]が入っているので、もう少し引っかかる人がいてもよさそうな気もするのだが。
http://github.com/rails/rails/commits/2-1-stable/railties/lib/tasks/databases.rake
普通はこの由来不明の環境変数VERSIONが存在しないのかもしれない。
一応、開発チームに報告だけはしておこうと思ったのだが、Railsの都合でrake.batを変えた場合、Railsチームに言うべきなのかRakeチームに言うべきなのか迷う。
ひとまずRakeは無いだろうということで、rake.batは変えずにRails内のRakefileの末尾に
ENV["VERSION"] = nil
する方法に変更。
何となくレポートを出してみたけど伝わるのか?書き方もよくわからんし。
#1203 [PATCH] When environment variable "VERSION" exists, db:migration will fail. - Ruby on Rails - rails