17

シンプルな 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

レシピ/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: undefined method '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 でモジュールを要求できるように、ライブラリ内のファイルを配置するためのシェフの変数はありますか。

ありがとう!

4

1 に答える 1

20

読み込み順序によっては、思ったよりも無名の Ruby クラスにモジュールをインクルードしている可能性があります。

メソッドをレシピで使用する場合は、レシピの上部で次のようにします。

include AppHelper

:sendまたは、ライブラリの最後で次を使用することもできます。

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

が定義されていない場合は例外が発生するため、これは異なりChef::Recipeます (存在しない場合は新しいクラスを作成しています)。

not_ifヘルパーとonly_ifガードを使用したい場合を除き、必要な作業はこれだけです。次に、ヘルパーをリソースに含める必要があります。

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

さて、すべてを説明したので、実際には役に立ちません。Ruby Block プロバイダーは単にブロックを呼び出すだけで、インスタンスを評価するわけではありません。そのため、ヘルパーをリソースに含めても何も起こりません

したがって、このインスタンスではシングルトン オブジェクトを使用する必要があります (これが、私が確実に考えることができる唯一の解決策です)。メソッドを定義した方法で、グローバル名前空間から直接呼び出すことができます。

AppHelper.find_gem('...')

そう:

ruby_block "find gem" do
  block do
    gem_bin = AppHelper.find_gem('...')
  end
end
于 2013-12-30T16:43:45.123 に答える