2016-10-25 2 views
0

Je suis en train de suivre this example, mais quand je ne peux pas trouver un moyen de boucle à travers le hachage comme il le fait:Looping par Ruby hachages

... 
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 
... 

Je reçois l'erreur suivante:

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

Pour une raison quelconque, le |a, (b,c)| ne fonctionne pas, les parenthèses sont ignorées.

On dirait que platform contient (comme prévu) 'myös', mais le iterator package est égal à « { "package"=> "package", "versions"=> [ "1.0", "2.0"," 3,0 "]} ' et versions est vide.

J'attends ce qui suit:

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

Je suis en mesure d'accéder au nom du package en boucle à travers les versions de la plate-forme.

Répondre

2

Essayez ceci. Chaque plate-forme a un nom et un ensemble d'attributs. Chaque attribut a un nom et une valeur.

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

Ceci est proche de ce dont j'ai besoin, mais je dois pouvoir accéder au nom du paquet sur chaque version de la liste. En boucle de cette façon, je ne peux avoir accès au nom du paquet qu'à la première itération, et je ne pense pas qu'il soit approprié de stocker cette valeur sur une variable externe. – Navarro

+0

Je voulais reproduire ce que vous fournissez en tant que sortie nécessaire. Si c'est quelque chose de différent, veuillez mettre à jour la question et je vais changer ma réponse. – Ursus

+0

Dans mon exemple, vous avez des versions dans 'platform ['versions']' – Ursus

1

Si nous avons

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

et

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

le premier (et seul) élément (paire clé-valeur) de platforms qui est passé au bloc est

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

Vous attribuez le bloc les variables à cette valeur:

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

Par cession parallèle (parfois appelée assignation multiple), Ruby obtient:

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

Ensuite, en appliquant la cession en parallèle une nouvelle fois, elle obtient:

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

ce qui n'est pas ce que vous voulez. Ce résultat ne devrait pas non plus être surprenant, étant donné que platform.first ne contient que deux éléments. Au lieu de cela, vous voulez deux variables de bloc, platform, h afin que

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

puis dans le bloc, vous aurez besoin de manipuler le hachage h.

+0

Très instructif, merci. – Navarro