命名空间下的Rake任务变量

时间:2015-05-19 14:15:22

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

我今天在rake脚本中看到了一件奇怪的事情。我在不同的命名空间下有两个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打印

/家庭/ Tomcat的/生产的Tomcat

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

知道为什么这个kolavari? :)

提前致谢!!

2 个答案:

答案 0 :(得分:2)

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

首先为path分配一个值:

path = "/home/tomcat/tomcat"

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

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

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

接下来,您创建java_deploy任务,但它尚未运行。此任务引用path变量,但在调用任务时,它的值可能已更改。

稍后,在定义production命名空间时,此变量将再次重新分配 。重要的是,仍然是相同的变量

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

当任务实际运行时,它引用path变量,此变量的值是分配给它的最新值,即/home/tomcat/production-tomcat

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

答案 1 :(得分:0)

除了matt的正确答案:

<块引用>

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

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

所以我建议添加一些检查来检测您是否收到错误: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>'