我今天在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? :)
提前致谢!!
答案 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>'