如何在厨师ruby_block中要求我的库

时间:2013-12-30 08:05:06

标签: chef cookbook

我正在开发一本食谱来部署一个简单的ROR应用程序。我写了一个app_helper.rb并把它放到我的cookbook的libraries目录中,这里是内容:

module AppHelper

    def self.find_gem
      if File.exists?("/usr/local/rvm/bin/rvm")
        return `/usr/local/rvm/bin/rvm default exec which gem`.chomp
      else
        return "/usr/bin/gem"
      end
    end
  end

在recipes / default.rb中,我将上面的模块混合到Chef :: Recipe类

class Chef::Recipe
  include AppHelper
end

如您所知,可以从配方的任何位置调用find_gem函数。

当我试图在我的ruby_block中使用find_gem函数时:

ruby_block "find gem" do
   block do
    gem_bin = Chef::Recipe::find_gem
    # or gem_bin = find_gem
  end
end

我得到了NoMethodError:未定义的方法'find_gem'。

还尝试将模块混合到Chef :: Resource :: RubyBlock中,它也不起作用。

class Chef::Resource::RubyBlock
  include AppHelper
end

ruby_block "find gem" do
   block do
    gem_bin = Chef::Resource::RubyBlock::find_gem
    # or gem_bin = find_gem
  end
end

有没有办法从ruby_block调用模块中的函数?或者是否有一个厨师变量来定位库中的文件,以便我能够在ruby_block中需要该模块。

谢谢!

1 个答案:

答案 0 :(得分:17)

根据加载顺序,您可能会将模块包含在匿名的Ruby类中,而不是您的想法。

如果您想在食谱中使用您的方法,请在食谱顶部执行此操作:

include AppHelper

您也可以在图书馆的末尾使用:send

Chef::Recipe.send(:include, AppHelper)

这是不同的,因为如果未定义Chef::Recipe,它将引发异常(而如果它不存在则创建新类)。

除非您想在not_ifonly_if警卫中使用帮助器,否则您应该做的就是这一切。然后,您需要在资源中包含帮助程序:

Chef::Resource.send(:include, AppHelper)

好的,既然我解释了所有这些,它实际上对你没有帮助。 Ruby Block提供程序只是calls the block - 它没有实例评估它。因此,在资源中包含帮助程序不会做任何事情

因此,在这个实例中你需要使用一个单例对象(这是我能够可靠地想到的唯一解决方案)。您定义方法的方式,可以直接从全局命名空间中调用它:

AppHelper.find_gem('...')

所以:

ruby_block "find gem" do
  block do
    gem_bin = AppHelper.find_gem('...')
  end
end