在哪里学习ruby DSL?

时间:2016-05-31 16:43:58

标签: ruby vagrant dsl

Vagrant.configure(2) do |config|
  config.vm.define "chefnode" do |chefnode|
    chefnode.vm.box = "geerlingguy/ubuntu1604"
    chefnode.vm.hostname = 'cnode'
    chefnode.vm.network "public_network"
  end

  config.vm.define "chefserver" do |chefserver|
    chefserver.vm.box = "geerlingguy/ubuntu1604"
    chefserver.vm.hostname = 'cserver'
    chefserver.vm.network "public_network"
  end
end

我在上面(流浪的dsl)代码上苦苦挣扎。这是Ruby DSL还是纯Ruby还是其他什么?为什么vm.box和vm.hostname有“=”符号,但vm.network没有?

2 个答案:

答案 0 :(得分:3)

首先是它的ruby,当你想创建自己的DSL时,它作为一种语言非常方便。所有的DSL都是使用像块(do ... end)这样的基础红宝石概念构建的 - 这里没有魔法。 在你的情况下,我们可能会说它是由Vagrant所有者创建的DSL。

为什么他们曾经使用=而另一次没有?在这个特定的情况下,我假设它是由于你有一个参数是一个字符串而且是必需的,后来你可以传递一个带有不同设置选项的哈希,比如文档中的例子。

Vagrant.configure("2") do |config|
  config.vm.network "forwarded_port", guest: 80, host: 8080
end

如果他们想使用=他们必须强制你传递一个Hash,其中需要名称密钥,其余的是可选的,我的意思是这样的:

config.vm.network = { name: "default" }

答案 1 :(得分:2)

这是标准的Ruby,没有DSL或元编程魔术。

Ruby在这方面很不寻常,但以下是chefserver.vm返回的对象的调用方法:

chefserver.vm.hostname = 'chefserver'  # calls method 'hostname='
chefserver.vm.network "public_network" # calls method 'network'

Ruby不需要在方法调用中使用括号(尽管有时需要向解释器说明你的意思)。

我不认识Chef,所以我不能说network调用为什么不是network=,除非在Ruby中调用名称以&#39结尾的方法; ='超过1个参数不起作用。虽然这里只指定了network的1个参数,但在Ruby中可以有可选的参数。该方法可能已经定义如下:

def network(name, something = 'foo')
  # ...
end

...这样可以使用1或2个参数调用该方法。