Как требовать мою библиотеку в chef ruby_block

Я разрабатываю поваренную книгу для развертывания простого приложения ROR. Я пишу app_helper.rb и помещаю его в каталог библиотек моей кулинарной книги, вот содержание:

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 можно вызывать из любой точки рецепта.

когда я пытаюсь использовать функцию find_gem в моем ruby_block следующим образом:

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

У меня есть метод NoMethodError: undefined '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

В зависимости от порядка загрузки вы можете включить свой модуль в анонимный класс Ruby вместо того, что вы думаете.

Если вы хотите использовать свой метод в рецепте, сделайте это в верхней части вашего рецепта:

include AppHelper

В качестве альтернативы вы можете использовать :send в конце вашей библиотеки:

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

Это другое, потому что оно вызовет исключение, если Chef::Recipe не определено (тогда как вы создаете новый класс, если он не существует).

Это все, что вам нужно сделать, если вы не хотите использовать помощника в защитных устройствах not_if и only_if. Затем вам нужно включить помощника в ресурс:

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

Хорошо, теперь, когда я объяснил все это, это на самом деле вам не поможет. Поставщик Ruby Block просто вызывает блок - он не имеет значения для eval. Поэтому включение помощника в ресурс не делает ничего.

Итак, вам понадобится использовать одноэлементный объект в этом экземпляре (это единственное решение, о котором я могу надеяться). Как вы определили свой метод, вы можете вызвать его непосредственно из глобального пространства имен:

AppHelper.find_gem('...')

Итак:

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