2016-10-25 5 views
0

Ich versuche this example zu folgen, aber wenn ich nicht einen Weg, um eine Schleife durch den Hash finden kann, wie er tut:durch Rubin Looping-Hashes

... 
platforms = { 
    'MyOS' => { 
    'package' => 'package', 
    'versions' => ['1.0', '2.0','3.0'] 
    } 
} 
... 
platforms.each do |platform, (package, versions)| 
    versions.each do |version| 
    context "On #{platform} #{version}" do 
    before do 
     Fauxhai.mock(platform: platform, version: version) 
    end 

    let(:chef_run) { ChefSpec::ChefRunner.new.converge('cookbook::recipe') } 

    it "Installs the package" do 
     chef_run.should install_package package 
    end 
    end 
end 
... 

bekomme ich folgende Fehlermeldung:

/path/file.rb:XX:in `block (2 levels) in <top (required)>': undefined method `each' for nil:NilClass (NoMethodError) 

Aus irgendeinem Grund funktioniert die |a, (b,c)| nicht, die runden Klammern werden ignoriert.

scheint wie platform enthält (wie erwartet) 'MYOS' jedoch der Iterator package gleich ‚{ "Paket"=> "Paket", "Varianten"=> [ "1,0", "2,0"," 3.0 "]} ' und versions ist leer.

Ich erwarte folgendes:

platform = "MyOS" 
package = "package" 
versions = ["1.0", "2.0", "3.0"] 

Also ich bin in der Lage den Paketnamen zuzugreifen, während durch die Versionen der Plattform Looping.

Antwort

2

Versuchen Sie es. Jede Plattform hat einen Namen und eine Reihe von Attributen. Jedes Attribut hat einen Namen und einen Wert.

platforms.each do |name, platform| 
    puts "platform = #{name}" 
    platform.each do |attribute, value| 
    puts "#{attribute} = #{value}" 
    end 
end 
+0

Dies ist nah an dem, was ich brauche, aber ich muss in der Lage sein, auf den Paketnamen für jede Version in der Liste zuzugreifen. Auf diese Weise kann ich nur auf den Paketnamen in der ersten Iteration zugreifen, und ich denke nicht, dass es angemessen ist, diesen Wert auf einer externen Variablen zu speichern. – Navarro

+0

Ich wollte reproduzieren, was Sie als Ausgabe zur Verfügung stellen. Wenn es etwas anderes ist, bitte aktualisieren Sie die Frage und ich werde meine Antwort ändern. – Ursus

+0

In meinem Beispiel haben Sie Versionen in 'platform ['versions']' – Ursus

1

Wenn wir

platforms = { 'MyOS' => { 'package'=>'package', 'versions' => ['1.0', '2.0','3.0'] } } 

und

platforms.each do |platform, (package, versions)|... 

die erste (und einzige) Element (Schlüssel-Wert-Paar) von platforms haben, die an den Block übergeben wird, ist

platforms.first 
    #=> ["MyOS", {"package"=>"package", "versions"=>["1.0", "2.0", "3.0"]}] 

Sie weisen den Block zu Variablen auf diesen Wert:

platform, (package, versions) = ["MyOS", {"package"=>"package", 
    "versions"=>["1.0", "2.0", "3.0"]}] 

Durch parallel Zuordnung (manchmal auch als Mehrfachzuordnung), Rubin erhält:

platform   #=> "MyOS" 
package, version #=> {"package"=>"package", "versions"=>["1.0", "2.0", "3.0"]} 

dann durch wieder einmal parallel Zuweisung der Anwendung sie erhält:

package   #=> {"package"=>"package", "versions"=>["1.0", "2.0", "3.0"]} 
versions   #=> nil 

was nicht das ist, was Sie wollen. Auch sollte dieses Ergebnis nicht überraschend sein, wenn man bedenkt, dass platform.first nur zwei Elemente enthält. Stattdessen wollen Sie zwei Blockgrößen, platform, h so dass

platform, h = ["MyOS", {"package"=>"package", "versions"=>["1.0", "2.0", "3.0"]}] 
platform #=> "MyOS" 
h #=> {"package"=>"package", "versions"=>["1.0", "2.0", "3.0"]} 

dann innerhalb des Blocks müssen Sie den Hash-h manipulieren.

+0

Sehr lehrreich, danke. – Navarro