2013-03-24 10 views
17

Qual è il modo migliore per fare un po 'secco all'interno di una ricetta cuoco? Cioè basta scovare piccoli frammenti del codice Ruby, quindi non lo copro più e più volte.DRY all'interno di una ricetta Chef

Di seguito fallisce naturalmente, con:

NoMethodError: undefined method `connect_root' for Chef::Resource::RubyBlock 

io possa avere più ruby_blocks in una ricetta, come fanno cose diverse e bisogno di avere diversi not_if blocchi per essere idempotente Truley.

def connect_root(root_password) 
    m = Mysql.new("localhost", "root", root_password) 
    begin 
    yield m 
    ensure 
    m.close 
    end 
end 

ruby_block "set readonly" do 
    block do 
    connect_root node[:mysql][:server_root_password] do |connection| 
     command = 'SET GLOBAL read_only = ON' 
     Chef::Log.info "#{command}" 
     connection.query(command) 
    end 
    end 
    not_if do 
    ro = nil 
    connect_root node[:mysql][:server_root_password] do |connection| 
     connection.query("SELECT @@read_only as ro") {|r| r.each_hash {|h| 
     ro = h['ro'] 
     } } 
    end 
    ro 
    end 
end 

risposta

23

Come già capito, non è possibile definire le funzioni nelle ricette. Per quello sono fornite le librerie. È necessario creare un file (ad esempio mysql_helper.rb) all'interno librerie cartella nel libro di cucina con il seguente:

module MysqlHelper 
    def self.connect_root(root_password) 
    m = Mysql.new("localhost", "root", root_password) 
    begin 
     yield m 
    ensure 
     m.close 
    end 
    end 
end 

E necessario essere un modulo, non è una classe. Si noti inoltre che lo definiamo come statico (usando self.method_name). Allora si sarà in grado di utilizzare le funzioni definite in questo modulo nelle vostre ricette con nome del modulo con nome del metodo:

MysqlHelper.connect_root node[:mysql][:server_root_password] do |connection| 
    [...] 
end 
+0

non ho provato, ma la sua una risposta completa, con l'esempio. Grazie! Sono triste nel vedere che devo creare un'intera libreria di libri di cucina per chef per una piccola funzione che non verrà utilizzata da nessun'altra parte. Ma comunque. – DragonFax

+1

Se si desidera utilizzare i metodi di istanza in modo da non dover prefisso con il nome della classe, si dovrebbe solo fare ':: :: Chef Recipe.send (: include, MysqlHelper)' e poi si può solo chiamare 'connect_root 'direttamente. –

+0

Grazie @JohnMorales. La risposta accettata è stata perfetta, ma la linea si è aggiunto (vedi sotto) ottenuto lavorando a compimento: :: :: Chef Recipe.send (: include, MysqlHelper) – KLaw

1

Per la cronaca, ho appena creato una libreria con il seguente. Ma sembra eccessivo per DRY all'interno di un file. Inoltre non sono riuscito a capire come ottenere qualsiasi altro spazio dei nomi per il modulo da utilizzare, per funzionare.

class Chef 
    class Resource 
    def connect_root(root_password) 
     ... 
+8

La documentazione per le biblioteche in libri di cucina Chef è del tutto inadeguato e fortemente ambigua. – DragonFax

+2

Non si deve tenere conto della classe Resource. È molto meglio creare un modulo e indirizzare i metodi attraverso il modulo. –

Problemi correlati