如何将此case语句更改为if语句?

时间:2013-01-05 08:48:56

标签: ruby chef

我想检查节点属性的值。这个case声明是我到目前为止所做的,并且有效:

case node[:languages][:ruby][:host_cpu]
   when "x86_64"
   ...
   when "i686"
   ...
end

我想要做的是使用if语句。这就是我试过的:

if node[:languages][:ruby][:host_cpu]?("X86_64")
   ...
end

这基于以下内容,其中有效。

if platform?("ubuntu")
    ...
end

但是,我的尝试没有用。它在if行上出现语法错误,表示预计会出现意外\n$end

我发现执行if有两种方法。第一个是我上面演示的那个(显然)只适用于资源,而if_only适用于节点。像这样

if_only {node[:languages]} 

似乎仅用于检查节点的存在,以及在do上下文中。

如何使用if语句检查节点的值?一种方法检查值,但仅检查资源,另一种检查节点,但仅检查它们的存在,而不是它们的值。

1 个答案:

答案 0 :(得分:8)

你正在混淆许多不同的条件变体,其中大多数都是Chef的一部分,而不是Ruby。让我试着逐一描述不同的选择。

通常,case与一系列ifelsif语句大致相当。您的case以上

case node[:languages][:ruby][:host_cpu]
   when "x86_64"
   ...
   when "i686"
   ...
end
因此

大致相当于

if node[:languages][:ruby][:host_cpu] == "x86_64"
  ...
elsif node[:languages][:ruby][:host_cpu] == "i686"
  ...
end

作为旁注,case实际上使用的===运算符通常不是可交换的,但更强大。对于简单的比较,它的工作方式与==相同。这两个变体都是Ruby语言的一部分,您可以在其中编写烹饪书。

您提到的其他选项实际上是Chef在Ruby上定义的API的一部分。这通常称为Chef DSL(代表域特定语言,即语言的扩展或改编,在本例中为特定用法域的Ruby,在本例中为配置管理。)

platform?方法是由Chef定义的方法,用于检查curent平台是否是传递的值之一。您可以阅读更多相关信息(以及类似的方法,例如,recipes in generaloften used ruby idioms的主厨文档中现在推荐的platform_family?方法。

作为旁注:您可能会对Ruby允许?!字符出现在方法名称的末尾这一事实感到惊讶,这使得Ruby在类似语言中相当独特。对此。这些字符只是方法名称的一部分,对语言没有特殊意义。它们仅按惯例用于程序员以更好地识别方法的目的。如果一个方法最后有?,那么它将用于检查某些条件,并且预计会返回真值或假值。最后使用!的方法通常会执行一些潜在的危险操作,例如:改变对象,删除东西,......再次,这只是一种约定,不会被语言解释。

您提到的最后一个选项only_if和扩展名not_if用于定义Chef资源上的条件,以确保它们仅在某个条件为真时执行(或者使用{{ 1}},如果是假的话)。由于这些属性仅用于Chef资源,因此它们自然也由Chef定义。

要了解它们有用的原因,有必要了解Chef运行的方式。详情可在Anatomy of a Chef Run的说明中找到。重要的是,您基本上有两个执行阶段:资源编译和融合。在第一步中,执行定义资源的实际代码。在这里,您的not_if语句中的代码也将运行。在加载完所有配方并定义了所有资源后,Chef进入第二阶段,即Convergence阶段。在那里,运行执行更改的资源的实际实现(在存储包中创建文件和目录,......)。只有在此阶段,才会检查caseonly_if条件。

事实上,你可以观察到

之间的区别
not_if

file "/tmp/helloworld"
  action :create
  content "hello world"
end   

if File.exist?("/tmp/helloworld")
  file "/tmp/foobar"
    action :create
    content "foobar"
  end
end

在第一个变体中,在资源编译期间检查是否存在file "/tmp/helloworld" action :create content "hello world" end file "/tmp/foobar" action :create content "foobar" only_if{ File.exist?("/tmp/helloworld") } end 的条件。目前,尚未运行实际创建/tmp/foobar文件的代码,因为它仅在转换步骤中执行。因此,在第一次运行期间,将不会创建/tmp/helloworld文件。

然而,在第二个变体中,检查是使用/tmp/foobar完成的,在转换期间进行评估。在这里,您会注意到两个文件都是在第一次运行时创建的。

如果你想更多地了解条件的定义如何在Ruby方面起作用(你肯定应该),你可以阅读Ruby Blocks或多或少的代码片段。为了以后的执行而四处传播。

相关问题