命名空间下的 Rake 任务变量

Rake task variable under namespace

我今天在我的佣金脚本中看到了一件奇怪的事情。我在不同的命名空间下有两个 Rake 任务,如下所示:

path = "/home/tomcat/tomcat"

namespace :stage do
  path = "/home/tomcat/stage-tomcat"
  desc "Deploys a java application to stage tomcat"
  task :java_deploy do
    puts path # stage:java_deploy should print /home/tomcat/stage-tomcat
  end
end

namespace :production do
  path = "/home/tomcat/production-tomcat"
  desc "Deploys a java application to production tomcat"
  task :java_deploy do
    puts path # production:java_deploy should print /home/tomcat/production-tomcat
  end
end

当我 运行: rake stage:java_deploy 它打印

/home/tomcat/production-tomcat

我期待 /home/tomcat/stage-tomcat。如果我从 rake 文件中删除第一行 path = "/home/tomcat/tomcat",它会按预期工作。

知道为什么要用这个 kolavari 吗? :)

提前致谢!!

这不是 Rake 特有的,它只是词法范围和 Ruby 处理局部变量的方式的结果,在第一次使用时声明它们。

首先你给path赋值:

path = "/home/tomcat/tomcat"

然后创建 stage 命名空间并重新分配变量:

path = "/home/tomcat/stage-tomcat"

请注意,无论您指定什么任务,都会执行此行,因为它不在任何任务中。

接下来创建 java_deploy 任务,但它还没有得到 运行。此任务引用 path 变量,但当调用该任务时,它的值可能已更改。

稍后,在定义 production 命名空间时,此变量会再次被重新分配 。重要的是,这 仍然是同一个变量 :

path = "/home/tomcat/production-tomcat"

当task实际是运行时,它引用了path这个变量,这个变量的值是最新赋给它的值,也就是/home/tomcat/production-tomcat.

当您删除对 path 的第一个赋值时,该变量将不存在于顶层。这意味着当您在每个命名空间定义中分配给 path 时,您在每种情况下都声明了一个新的(和单独的)局部变量。

除了matt的正确答案:

When you remove the first assignment to path, then the variable doesn’t exist in the top level. This means that when you assign to path in each namespace definition you are declaring a new (and separate) local variable in each case.

如果您以后再定义变量,您可能会遇到奇怪的错误,并且很难找到问题的根源。

所以我建议添加一点检查来检测您是否收到错误:raise ArgumentError, "Variable path may not defined before thos scope" if defined? path

示例:

require 'rake'
#path = "/home/tomcat/tomcat" #this results in an Exception if uncommented

namespace :stage do
  raise ArgumentError, "Variable path may not defined before thos scope" if defined? path
  path = "/home/tomcat/stage-tomcat"
  desc "Deploys a java application to stage tomcat"
  task :java_deploy do
    puts path # stage:java_deploy should print /home/tomcat/stage-tomcat
  end
end

namespace :production do
  raise ArgumentError, "Variable path may not defined before thos scope" if defined? path
  path = "/home/tomcat/production-tomcat"
  desc "Deploys a java application to production tomcat"
  task :java_deploy do
    puts path # production:java_deploy should print /home/tomcat/production-tomcat
  end
end

根据第 2 行,您的脚本将运行或抛出异常:

test.rb:5:in `block in <main>': Variable path may not defined before this scope (ArgumentError)
  from C:/.../rake/task_manager.rb:224:in `in_namespace'
  from C:/.../rake/dsl_definition.rb:141:in `namespace'
  from test.rb:4:in `<main>'