关于ruby on rails:rake db:migrate不会检测到新的迁移?

关于ruby on rails:rake db:migrate不会检测到新的迁移?

rake db:migrate doesn't detect new migration?

熟悉Rails / ActiveRecord 2.1.1

  • 您使用(例如)ruby script generate scaffold产品标题创建一个第一个版本:字符串描述:文本image_url:string
  • 此操作创建(例如)一个名为20080910122415_create_products.rb的迁移文件
  • 您可以通过rake db:migrate应用迁移
  • 现在,您使用ruby script generate migration add_price_to_product price:decimal将字段添加到产品表
  • 这将创建一个名为20080910125745_add_price_to_product.rb的迁移文件
  • 如果您尝试运行rake db:migrate,它将实际上还原第一个迁移,而不应用下一个!这样您的产品表将被销毁!
  • 但是,如果您独自一人进行耙,它会告诉您一次迁移正在等待中

请注意,应用rake db:migrate(一旦表被销毁)将按顺序应用所有迁移。

我发现的唯一解决方法是指定新迁移的版本,如下所示:

1
rake db:migrate version=20080910125745

所以我想知道:这是预期的新行为吗?


敬请谅解,汤姆!这是一个错误! V3.5.0f不是用于rake迁移的有效版本。 Rake不应仅因为ruby选择将" V3.5.0f" .to_i视为0才将其迁移到:down ...

Rake应该大声抱怨VERSION无效,以便用户知道最新情况
(在您和我之间,通过转换为整数来检查版本是否为YYYYMMDD格式的时间戳有点麻烦)

[该死的IE6,不允许我发表评论!而且不,我不能更改浏览器,谢谢企业]


您应该可以使用

1
rake db:migrate:up

迫使它继续前进,但随后您就有可能错过团队中其他人的交错迁移

如果你跑

1
rake db:migrate

两次,它将重新应用您的所有迁移。

我在使用SQLite的Windows上遇到相同的行为,这可能是特定于这种环境的错误。

编辑-我找到了原因。在railstie database.rake任务中,您具有以下代码:

1
2
3
4
5
6
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

然后在我的环境变量中

1
echo %Version% #=> V3.5.0f

在Ruby中

1
2
ENV["VERSION"] # => V3.5.0f
ENV["VERSION"].to_i #=>0 not nil !

因此耙任务调用

1
ActiveRecord::Migrator.migrate("db/migrate/", 0)

在ActiveRecord :: Migrator中,我们有:

1
2
3
4
5
6
7
8
9
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
    end

是的,rake db:migrate VERSION=0rake db:migrate:down的长版本

编辑-我会去更新灯塔的bug,但是我超级公司代理禁止我在那里连接

同时,您可以在调用迁移之前尝试取消设置版本...


非常感谢您的调查。您是对的,实际上我认为您已经发现了一个更严重的错误,即"设计错误"。

发生的情况是,rake将获取您传递给命令行的任何值并将其存储为环境变量。最终将被调用的rake任务只会从环境变量中提取此值。
当db:migrate查询ENV [" VERSION"]时,它实际上会请求您设置调用rake的version参数。调用rake db:migrate时,不会传递任何版本。

但是,我们确实有一个名为VERSION的环境变量,该变量已由其他一些程序设置用于其他目的(我还没有)。和rake(或database.rake)背后的人还没有想到会发生这种情况。那是一个设计错误。至少,他们可以使用更具体的变量名,例如" RAKE_VERSION"或" RAKE_PARAM_VERSION",而不仅仅是" VERSION"。

汤姆,我当然不会关闭,但会在灯塔上编辑我的错误报告以反映这些新发现。

再次感谢Jean的帮助。我已经像5天前那样在灯塔上发布了这个错误,但仍然没有答案!

罗洛


这不是预期的行为。我本来建议将此报告为灯塔上的错误,但我发现您已经这样做了!如果您提供更多信息(包括OS /数据库/ ruby??版本),我将进行介绍。


推荐阅读