【问题标题】:Does invoking multiple tasks from a parent rake loads environment for each of them是否从父 rake 加载环境中为每个任务调用多个任务
【发布时间】:2014-08-13 07:25:07
【问题描述】:

如果我有一个 rake 会调用多个其他 rake。

一旦我启动了父 rake

rake myapp:main

然后在 rake 中完成的调用将为每个任务加载环境,或者在运行 rake myapp:main 时只完成一次活动?

namespace :myapp do
  desc "Main Run"
  task :main => :environment do
    Rake::Task['myapp:task1'].invoke
    Rake::Task['myapp:task2'].invoke
  end

  task :task1 => :environment do
    # Does the first task
  end

  task :task2 => :environment do
    # Does the second task
  end
end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3.2 rake rake-task


    【解决方案1】:

    在@Shadwell 的回答中添加详细信息..

    => :environment 指定 :environment 任务(由 rails 定义)是您的任务的依赖项,必须在您的任务之前调用。

    你可以在这里看到:environment任务的定义

    https://github.com/rails/rails/blob/d70ba48c4dd6b57d8f38612ea95a3842337c1419/railties/lib/rails/application.rb#L428-432

    Rake 会跟踪调用了哪些任务,当它到达一个已经被调用的依赖项时,它知道可以跳过它。

    https://github.com/jimweirich/rake/blob/5e59bccecaf480d1de565ab34fd15e54ff667660/lib/rake/task.rb#L195-204

    # Invoke all the prerequisites of a task.
    def invoke_prerequisites(task_args, invocation_chain) # :nodoc:
      if application.options.always_multitask
        invoke_prerequisites_concurrently(task_args, invocation_chain)
      else
        prerequisite_tasks.each { |p|
          prereq_args = task_args.new_scope(p.arg_names)
          p.invoke_with_call_chain(prereq_args, invocation_chain)
        }
      end
    end
    

    Rake 维护一个实例变量@already_invoked 以了解是否已经调用了任务。在下面的方法中可以看到同样的情况

    https://github.com/jimweirich/rake/blob/5e59bccecaf480d1de565ab34fd15e54ff667660/lib/rake/task.rb#L170-184

    def invoke_with_call_chain(task_args, invocation_chain) # :nodoc:
      new_chain = InvocationChain.append(self, invocation_chain)
      @lock.synchronize do
        if application.options.trace
          application.trace "** Invoke #{name} #{format_trace_flags}"
        end
        return if @already_invoked
        @already_invoked = true
        invoke_prerequisites(task_args, new_chain)
        execute(task_args) if needed?
      end
    rescue Exception => ex
      add_chain_to(ex, new_chain)
      raise ex
    end
    

    【讨论】:

    • 感谢您的详细解释。
    【解决方案2】:

    环境只会设置一次。

    => :environment 指定 :environment 任务(由 rails 定义)是您的任务的依赖项,并且必须在您的任务之前调用。 Rake 会跟踪调用了哪些任务,当它到达一个已经被调用的依赖项时,它知道可以跳过它。

    (顺便说一句:如果您确实希望多次调用依赖项,这可能会导致问题)

    您还可以使用依赖项定义您的 main 任务:

    task :main => [:task1, :task2] do
      # Blank
    end
    

    当您运行rake myapp:main 时,它将查看依赖关系并调用task1,然后调用task2。因为task1 有一个依赖environment,它也会首先调用它。它会跳过 environmenttask2 的依赖。

    【讨论】:

      【解决方案3】:

      答案是否定的,从父任务执行另一个 Rake 任务时未加载环境。对此的简单解释是下面的代码:

      namespace :myapp do
        desc "Main Run"
        task :main => :environment do
          puts "Start Time : #{Time.now.to_i}"
          Rake::Task['myapp:task1'].invoke
          puts "End Time1 : #{Time.now.to_i}"
          Rake::Task['myapp:task2'].invoke
          puts "End Time2 : #{Time.now.to_i}"
        end
      
        task :task1 => :environment do
          # Does the first task
          puts "Executing..1"
        end
      
        task :task2 => :environment do
          # Does the second task
          puts "Executing..2"
        end
      end
      

      但是执行两个或多个 rake 任务并不是一个好习惯。如果想达到同样的效果,可以将代码模块化,创建两个函数,调用函数,达到同样的效果。

      【讨论】:

        猜你喜欢
        • 2012-04-04
        • 1970-01-01
        • 2014-02-27
        • 2015-06-17
        • 1970-01-01
        • 1970-01-01
        • 2012-02-13
        • 2019-11-28
        • 2017-06-10
        相关资源
        最近更新 更多