2017-04-24 6 views
1

Mon application passe à différentes méthodes json_element pour lesquelles les clés sont différentes, et parfois vides.en utilisant ruby ​​pour extraire les valeurs dans un hachage de manière DRY

Pour gérer, je suis hardcoding l'extraction avec le code exemple suivant:

def act_on_ruby_tag(json_element) 

begin 

    # logger.progname  = __method__ 
    logger.debug    json_element 

    code     = json_element['CODE']['$'] unless json_element['CODE'].nil? 
    predicate    = json_element['PREDICATE']['$'] unless json_element['PREDICATE'].nil? 
    replace    = json_element['REPLACE-KEY']['$'] unless json_element['REPLACE-KEY'].nil? 
    hash     = json_element['HASH']['$'] unless json_element['HASH'].nil? 

Je voudrais éliminer hardcoding les valeurs, et pas tout à fait sûr de savoir comment.

j'ai commencé à réfléchir comme suit:

keys = json_element.keys 
keys.each do |k| 
     set_key = k.downcase 
     instance_variable_set("@" + set_key, json_element[k]['$']) unless json_element[k].nil? 
     end 

Et puis utilisez @code par exemple dans le reste de la méthode. J'allais essayer de transformer en une méthode, puis remplacer tout ce code codé en dur.

Mais je n'étais pas entièrement sûr si c'est un bon chemin.

Répondre

3

Il est presque toujours préférable de renvoyer une structure de hachage d'une méthode où vous avez des choses comme { code: ... } plutôt que de définir des variables d'instance arbitraires. Si vous les renvoyez dans un conteneur cohérent, il est plus facile pour les appelants de les livrer au bon endroit, de les stocker pour plus tard, ou de choisir ce qu'ils veulent et d'abandonner le reste.

C'est aussi une bonne idée d'essayer de briser un grand pas maladroit avec une série d'opérations plus petites et plus légères. Cela rend le code beaucoup plus facile à suivre:

def extract(json) 
    json.reject do |k, v| 
    v.nil? 
    end.map do |k, v| 
    [ k.downcase, v['$'] ] 
    end.to_h 
end 

Ensuite, vous obtenez ceci:

extract(
    'TEST' => { '$' => 'value' }, 
    'CODE' => { '$' => 'code' }, 
    'NULL' => nil 
) 
# => {"test"=>"value", "code"=>"code"} 

Si vous voulez persister tout cela comme une variable d'instance, qui est un modèle assez typique, mais il aura un nom prévisible qui n'est pas à la merci de n'importe quel document JSON arbitraire que vous consommez.

Une alternative consiste à coder en dur les clés dans une comme constante:

KEYS = %w[ CODE PREDICATE ... ] 

Utilisez ensuite qu'au lieu ou un peu plus loin, de nis dans un fichier YAML ou JSON vous pouvez lire dans la configuration fins. Cela dépend vraiment de la fréquence à laquelle ceux-ci vont changer, et quel genre d'attentes vous avez sur l'irrégularité de l'entrée.

+0

Merci ... Je compris que le « $ » est en fait un Artfact d'utiliser CobravsMongoose gem.BUT ... le vrai problème est ce que vous discuterez .... pour retirer les clés et de vérifier s'il y a une valeur ou non sans erreur. Parfois l'une des clés n'a aucune valeur - elle est vide. C'est pourquoi j'ai la vérification "nil?" – Angela

+0

Vide et «nil?» Sont deux choses différentes, gardez cela à l'esprit. Si vous cherchez simplement des choses dans lesquelles vous pouvez naviguer, un test par rapport à «v» est suffisant. Le code minimal est généralement plus facile à déboguer. – tadman

0

Il s'agit d'une façon un peu plus succincte de faire ce que votre code original fait.

code, predicate, replace, hash = json_element.values_at *%w{ 
    CODE PREDICATE REPLACE-KEY HASH 
}.map { |x| x.fetch("$", nil) if x } 
+0

dans ces cas, je devrais savoir Aprori que les clés sont «code, prédicat, remplacer ... etc»? Ceux qui changent à chaque fois ..... penser si cela aide à savoir à l'avance ... il pourrait .... – Angela

+0

Comment puis-je analyser ceci - je peux être capable de créer ceci sans l'artefact '$'. – Angela

+0

Ceci est un moyen d'extraire 4 clés particulières dans des variables de niveau supérieur, sans utiliser la métaprogrammation. Comme souvent à Ruby il y a plusieurs façons de faire la même chose –