2012-04-27 15 views
6

estoy seguro de que he visto una elegante solución a esto antes, pero no puedo encontrarlo:manejo de valores en blanco en un resumen anidada

tengo un controlador de raíles que puedan-o-mayo -no tiene el siguiente elemento hash:

myhash[:parent_field] 

Dentro de ese campo principal, un elemento secundario también podría estar en blanco. Actualmente estoy comprobando que a través del método (muy feo):

if (!myhash[:parent_field] || !myhash[:parent_field][:child_field] || myhash[:parent_field][:child_field].blank?) 

que funciona, pero calculo - sin duda - que tiene que haber una forma más elegante. Sólo para reiterar:

  • myhash [: parent_field] puede o no puede existir
  • Si existe, myhash [: parent_field] [: child_field] puede o no existir
  • Si lo que existe, se puede o no estar en blanco.

Respuesta

9

#fetch es su amigo:

my_hash.fetch(:parent, {})[:child].blank? 
+0

Tenga en cuenta que esto generará una excepción si la clave ': parent' no existe. –

+0

@AndrewMarshall No, no lo hará. Lea sobre lo que hace buscar. – d11wtq

+0

Lo siento, no vi el segundo argumento allí. Sin embargo, lo hará si no lo hay. –

0

Probablemente dependa de cuáles sean sus necesidades reales, pero un enfoque de OOP sería convertir las matrices y hashes en objetos reales. Cada objeto gestionaría sus relaciones (similar a ActiveRecord) y sabría cómo obtener hijos y padres.

3

Lo que yo haría se acaba de utilizar variables locales para aliviar su carga:

unless (p=foo[:parent]) && (c=p[:child]) && !c.blank? 
    # Stuff is borked! 
end 

Pero vamos a explorar alternativas, para la diversión y hellip;


Si no puede cambiar su estructura de datos (que es un hash, por cierto, no una matriz), puede utilizar el Rubí andand joya en conjunción con try maneras como perezosos los rieles de llamar métodos en cosas que podrían ser objetos nil.


Se podría, alternativamente, cambiar su estructura de datos de hashes que devuelven valores hash de auto-vivifying vacías cuando se pide una clave que no existe:

mine = Hash.new{ |h,k| Hash.new(&h.default_proc) } 
mine[:root] = { dive:42 } 
p mine[:root][:dive]  #=> 42 
p mine[:ohno][:blah][:whee] #=> {} 
p mine[:root][:blah][:whee] #=> undefined method `[]' for nil:NilClass (NoMethodError) 

Sin embargo, usted tendría que asegurarse de que cada objeto en su jerarquía era uno de estos hashes (que explícitamente no pude hacer para el contenido de :dive, lo que dio como resultado el error).


Para la diversión alternativa, se puede añadir su propio método de búsqueda de la magia:

class Hash 
    def divedive(*keys) 
    obj = self 
    keys.each do |key| 
     return obj unless obj && obj.respond_to?(:[]) 
     obj = obj[key] 
    end 
    obj 
    end 
end 

if myarray.divedive(:parent,:child).blank? 
    # ... 
-2

¿Qué tal

!(myarray[:parent_field][:child_field] rescue nil).blank? 

?

0

Desde nil.blank? es true, puede eliminar la condición media y simplificar a esto:

if !myarray[:parent_field] || myarray[:parent_field][:child_field].blank? 

También, llamando a un Hash myarray es un poco engañoso.

1

Esta es una pregunta frecuente y probablemente debe ser cerrado como un duplicado de

La primera en esa lista se cerró como un DUP de los otros dos, aunque creo que mi respuesta allí tiene una cobertura más completa de las técnicas para abordar este problema que los últimos tw o

+0

Darn - tienes razón. Intenté buscar, pero no pude sacar nada relevante. He votado para cerrar. Y muchas gracias. :-) – PlankTon

Cuestiones relacionadas