2016-07-07 10 views
2

Ich habe eine YAML-Datei, die ein paar Tasten mit mehreren Werten und ein Paar mit einem Wert hat:Lese YAML mit Rubin, unerwartete Rückkehr Typ

inbox: 
    paul: 'PHILADELPHIA-RO-ADMIN' 
    tanny: 'PA-C-INDIANA-ADMIN' 
    mary: 
      - 'MD-C-LAUREL-ADMIN' 
      - 'MD-E-BALTIMORE-ADMIN' 
      - 'MD-R1-CAMBRIDGE-ADMIN' 
      - 'MD-R2-BELAIR-ADMIN' 
      - 'MD-R4-LAUREL-ADMIN' 
      - 'MD-R5-HAGERSTWN-ADMIN' 
    mike: 
      - 'VA-E-Richmond-Admin' 
      - 'VA-Richmond-Admin' 
      - 'VA-Manassas-Admin' 
      - 'VA-Norfolk-Admin' 
      - 'VA-Roanoke-Admin' 
      - 'VA-Verona-Admin' 

Was ich bin versucht zu tun ist, wenn der Schlüssel hat mehr als ein Wert ausgegeben der Schlüssel hat mehr als einen Wert, aber wenn der Schlüssel nur einen Wert hat, nur diesen Wert ausgeben. Ich versuche, die Array.count Funktion zu verwenden, um dies zu tun, ich habe über ein Problem kommen, wo, wenn das Array nur einen Wert hat es im Innern des Schlüssels Menge von Zeichen zählt, zum Beispiel:

require 'yaml' 

POC = YAML.load_file('test.yml') 

def get_poc(name) 

    data = POC['inbox'][name.downcase] 
    puts data.count 
    if data.count == 1 
    POC['inbox'][name] 
    else 
    puts "Multiple inboxes found for #{name.capitalize.chomp}" 
    data.each.with_index(1) do |str, i| 
     puts "#{i}. #{str}" 
    end 
    puts 'One of the above inboxes is the correct inbox for this ticket.' 
    end 
end 

Wenn dieses in IRB ausgeführt wird:

irb(main):020:0> get_poc('mary') 
6 
Multiple inboxes found for Mary 
1. MD-C-LAUREL-ADMIN 
2. MD-E-BALTIMORE-ADMIN 
3. MD-R1-CAMBRIDGE-ADMIN 
4. MD-R2-BELAIR-ADMIN 
5. MD-R4-LAUREL-ADMIN 
6. MD-R5-HAGERSTWN-ADMIN 
One of the above inboxes is the correct inbox for this ticket. 
=> nil 
irb(main):021:0> get_poc('paul') 
21 
ArgumentError: wrong number of arguments (given 0, expected 1+) 
     from (irb):10:in `count' 
     from (irb):10:in `get_poc' 
     from (irb):21 
     from C:/Ruby23/bin/irb.cmd:19:in `<main>' 
irb(main):022:0> 

es scheint, dass es für mehrere Werte funktioniert, aber wenn man sich nur ein Wert ist es über die gesamte Länge des Wertes von Zeichen tatsächlich zu zählen scheint.

Ich habe auch versucht die Array.length Methode:

require 'yaml' 

    POC = YAML.load_file('test.yml') 

    def get_poc(name) 

     data = POC['inbox'][name.downcase] 
     puts data.length 
     if data.length == 1 
     POC['inbox'][name] 
     else 
     puts "Multiple inboxes found for #{name.capitalize.chomp}" 
     data.each.with_index(1) do |str, i| 
      puts "#{i}. #{str}" 
     end 
     puts 'One of the above inboxes is the correct inbox for this ticket.' 
     end 
    end 

gleiche Problem unterschiedliche Fehler:

irb(main):040:0> get_poc('mary') 
6 
Multiple inboxes found for Mary 
1. MD-C-LAUREL-ADMIN 
2. MD-E-BALTIMORE-ADMIN 
3. MD-R1-CAMBRIDGE-ADMIN 
4. MD-R2-BELAIR-ADMIN 
5. MD-R4-LAUREL-ADMIN 
6. MD-R5-HAGERSTWN-ADMIN 
One of the above inboxes is the correct inbox for this ticket. 
=> nil 
irb(main):041:0> get_poc('paul') 
21 
Multiple inboxes found for Paul 
NoMethodError: undefined method `each' for "PHILADELPHIA-RO-ADMIN":String 
     from (irb):34:in `get_poc' 
     from (irb):41 
     from C:/Ruby23/bin/irb.cmd:19:in `<main>' 
irb(main):042:0> 

Wie kann ich die Methode bekommen nur den Wert als ein Element zu zählen?

Antwort

2

Die Wurzel des Problems ist, dass POC['inbox'][name.downcase] verschiedene Objekte zurück:

  1. Wenn ein einzelnes Element, ein String zurückgegeben.
  2. Wenn eine Liste zurückgegeben wird, wird Array zurückgegeben.

Mit anderen Worten:

POC['inbox']['mary'].class 
#=> Array 
POC['inbox']['paul'].class 
#=> String 

count ist anders für diese 2 Klassen definiert.

Um zu überprüfen, dass ein Element ist, können Sie:

  1. Überprüfen Sie, ob die Daten eine String und
  2. Wenn ein String nicht prüfen, ob die count 1 (dh in dem Fall ist, dass ein Liste verwendet wird, aber es hat nur 1 Punkt)

Der aktualisierte if Zustand sein würde:

def get_poc(name) 
    data = POC['inbox'][name.downcase] 

    if data.kind_of?(String) || data.count == 1 
    POC['inbox'][name] 
    else 
    puts "Multiple inboxes found for #{name.capitalize.chomp}" 
    data.each.with_index(1) do |str, i| 
     puts "#{i}. #{str}" 
    end 
    puts 'One of the above inboxes is the correct inbox for this ticket.' 
    end 
end 
+0

Das einzige Problem ist, dass count nicht 1 zurückgibt, es gibt die Länge der Zeichenfolge zurück. Aber warum gibt es eine 'String' und keine' Array' zurück? – JohnDoeYo

+1

'count' und' length' haben eine andere Bedeutung für 'Strings', also nein, sie geben nicht die erwartete 1 zurück. Es wird ein String zurückgegeben, da dies in der YAML-Datei definiert ist. Eine Liste mit einem einzelnen Objekt müsste eine gestrichelte Liste sein. –

2

Sie verwenden die XML-Datei nicht konsistent, sodass Sie keine konsistenten Ergebnisse erhalten. Wenn Sie möchten, dass Paul ein Ein-Element-Array ist, müssen Sie ...

inbox: 
    paul: 
    - 'PHILADELPHIA-RO-ADMIN' 
... 

Oder Sie könnten es im Code beheben, indem nur eine Zeile zu ändern:

data = [POC['inbox'][name.downcase]].flatten 

diese Weise werden Sie immer ein Array erhalten, auch wenn der Schlüssel nur ein Element hat und der Rückgabewert String.

+0

Ich war immer unter den Eindrücken, dass ein Array immer von einem 'Yaml' zurückgegeben wurde. Das ist großartig, danke. – JohnDoeYo