【问题标题】:Why does a Rake task in a loop execute only once?为什么循环中的 Rake 任务只执行一次?
【发布时间】:2011-06-16 20:38:30
【问题描述】:

我有连接到多个数据库的 Rails 应用程序。我编写了如下所示的自定义 rake 任务:

task :migrate_accounts_schema => [:environment] do |t|
  users = User.find :all, :conditions => ["state = 2"], :order => "id asc"
  users.each do |user|            
    if user.state == 2
      ActiveRecord::Base.establish_connection(
        :adapter  => "postgresql",
        :host     => user.database_host,
        :port     => user.database_port,
        :username => user.subdomain,
        :password => "#{user.database_password}",
        :database => user.database_name
      )
      Rake::Task["db:migrate"].invoke
    end
  end
end

问题是任务只为 users[0] 用户(集合中的第一个用户)执行 db:migrate 并且没有错误,只是静默停止...

这是 rake --trace 的输出

** Invoke app:migrate_accounts_schema (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute app:migrate_accounts_schema    
** Invoke db:migrate (first_time)
** Invoke environment 
** Execute db:migrate
** Invoke db:schema:dump (first_time)
** Invoke environment 
** Execute db:schema:dump
** Invoke db:migrate 

我不知道为什么其他用户没有被迁移。

【问题讨论】:

    标签: ruby rake


    【解决方案1】:

    我在 Rake 源码中找到了答案:

    http://rake.rubyforge.org/classes/Rake/Task.html#M000115

    它说你必须

    重新启用任务,如果再次调用该任务,则允许执行其任务。

    例如我最近在我的项目中这样使用它:

    # db/seed.rb
    Rake::Task['catalog:destroy'].invoke
    
    files = Dir.glob("private/catalog/*").sort
    files.each do |file|
      next unless File.extname(file) == '.xlsx'
      puts file.split('/').last
      Rake::Task['catalog:upload'].invoke(file)
      Rake::Task['catalog:upload'].reenable
      puts
    end
    

    所以我运行 rake catalog:upload[some_file] 每个循环。

    希望这会有所帮助。 另见https://stackoverflow.com/a/1290119/3082929

    【讨论】:

    • 我很确定这是技术上正确的答案(#reenable,不仅仅是#execute
    【解决方案2】:

    我忘记了确切的内部结构,但 Rake 的工作方式是 invoke 只会在需要时执行每个任务(换句话说,一次)。

    尝试在后续调用中调用 execute:

    Rake::Task["db:migrate"].execute

    第一次通过循环时,您需要invoke,因为它首先调用先决条件。

    【讨论】:

    • 这对我来说似乎非常违反直觉。有什么想法为什么会这样?
    • 在这上面浪费了一个小时——无法弄清楚为什么在单元测试中没有多次调用该任务。谢谢!
    • 如果任务接受参数作为散列传递:Rake::Task["db:migrate"].execute(arg1: arg1, arg2: arg2, ...)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2016-04-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多