6

熟悉 Rails / ActiveRecord 2.1.1

  • 您使用(例如)ruby script\generate scaffold product title:string description:text 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,它会告诉你有一个迁移正在等待

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

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

rake db:migrate version=20080910125745

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

4

4 回答 4

1

你应该可以使用

rake db:migrate:up 

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

如果你跑

rake db:migrate 

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

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

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

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

然后在我的环境变量中我有

echo %Version% #=> V3.5.0f

在红宝石

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

因此 rake 任务调用

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

在 ActiveRecord::Migrator 我们有:

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=0是长版rake db:migrate:down

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

同时,您可以尝试在调用 migrate 之前取消设置 Version ...

于 2008-09-16T09:39:54.230 回答
0

这不是预期的行为。我本来建议将此报告为灯塔上的错误,但我看到您已经这样做了!如果您提供更多信息(包括操作系统/数据库/ruby 版本),我会看一下。

于 2008-09-16T09:50:29.977 回答
0

我恭敬地不同意汤姆!这一个错误!V3.5.0f 不是 rake 迁移的有效版本。Rake 不应该仅仅因为 ruby​​ 选择考虑 "V3.5.0f".to_i 是 0 就使用它来迁移:down ...

Rake 应该大声抱怨 VERSION 无效,以便用户知道发生了什么(在你我之间,通过转换为整数来检查版本是否是 YYYYMMDD 格式的时间戳有点轻)

[该死的IE6不允许我发表评论!不,我不能更改浏览器感谢公司]

于 2008-09-16T10:25:53.557 回答
0

让,

非常感谢您的调查。你是对的,实际上我认为你发现了一个更严重的错误,即物种“设计错误”。

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

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

汤姆,我绝对不会关闭,而是编辑我关于灯塔的错误报告以反映这些新发现。

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

罗洛

于 2008-09-16T10:41:03.473 回答