2013-10-02 6 views
5

Ich versuche, eine Bibliothek für ein Kochkochbuch zu schreiben, das einige allgemeine Suchen vereinfacht.Wie kann ich von einer Bibliothek in einem Koch-Kochbuch auf den aktuellen Knoten zugreifen?

Zum Beispiel würde Ich mag Lage sein, so etwas zu tun in cookbook/libraries/library.rb und es dann aus einem Rezepte in dem gleichen Kochbuch verwenden:

module Example 
    def self.search_attribute(attribute_name) 
     return search(:nodes, node[attribute_name]) 
    end 
end 

Das Problem ist, dass in einer Chef-Bibliotheksdatei weder das node Objekt noch die search Funktion sind verfügbar.

Die Suche scheint möglich zu sein mit Chef::Search::Query.new().search(...), aber ich kann nichts finden, das funktioniert, um auf node zuzugreifen. Der sich daraus ergebende Fehler lautet:

undefined local variable or method `node' for Example:Module 

Verwenden von Chef 10.16.4.

+0

Verwandte http://Stackoverflow.com/a/22081109/1626687 – spuder

Antwort

6

Sie können das Modul in Ihr Rezept aufnehmen. Auf diese Weise erhalten Ihre Modulfunktionen Zugriff auf die Methoden des Rezepts, einschließlich node.

ich tun dies in der Regel für meine Bibliothek Module:

# my_cookbook/libraries/helpers.rb 
module MyCookbook 
    module Helpers 
    def foo 
     node["foo"] 
    end 
    end 
end 

Dann in der Rezeptur ich das Modul in die aktuelle Instanz eines Rezeptes enthalten:

# my_cookbook/recipes/default.rb 
extend MyCookbook::Helpers 

Auf diese Weise nur die Aktuelles Rezept bekommt das Modul beigefügt, nicht alle im ganzen Koch laufen (so vermeiden Sie Namenskonflikte).

Alternativ können Sie den aktuellen Knoten als Parameter an die Funktion übergeben. Auf diese Weise müssen Sie das Modul nicht einschließen (was den Vorteil hat, dass die Modul-Namespaces beibehalten werden), hat aber den Nachteil eines komplexeren Methodenaufrufs.

+0

Wahrscheinlich eine dumme Frage, aber was meinst du mit "So, nur das aktuelle Rezept wird das Modul enthalten, nicht alle von ihnen in der ganzen Koch Lauf"? –

+2

Die Leute rufen oft 'Chef :: Rezept.include MyCookbook :: Helfer 'auf, wodurch die Hilfsfunktionen in allen Rezepten verfügbar sind (und möglicherweise bereits vorhandene mit demselben Namen überschrieben werden können). Ich denke, das ist ein Code-Geruch und bevorzuge meine Version, um das "Helfer" -Modul nur explizit in ein Rezept aufzunehmen. –

+0

Ich denke ich verstehe. Die Verwendung von Rubys Erweiterung würde nur die Methoden aus dem Modul zu dem einzelnen Rezeptobjekt hinzufügen, das ausgeführt wird, während die Verwendung von include, wie Sie es erwähnten, es allen Chef :: Rezeptobjekten hinzufügen würde. Vielen Dank! –

0

Ich habe gerade versucht, auf die aktuelle Umgebung in einer Bibliothek zuzugreifen. Ich konnte nicht wirklich herausfinden, wie man Module verwendet, um Zugang zu dem Knoten zu erhalten, und ich wollte den Knoten nicht in jeden Methodenaufruf (oder den Instantiierungsaufruf) übergeben, also tat ich dies (Beispielcode .. nicht die tatsächliche Funktionalität):

# libraries/account.rb 
class Account 
    @@env = "_default" 

    def self.env=(env) 
    @@env = env 
    end 

    def settings 
    Chef::EncryptedDataBagItem.load(@@env, "settings") || {} 
    end 
end 

# recipes/accounts.rb 
Account.env = node.chef_environment 

Account.new.settings 

ich weiß nicht, ob Klassenvariablen mit verpönt ist, aber es funktioniert in allen meinen Tests und es ist schön und einfach zu bedienen.

Verwandte Themen