2012-03-06 12 views
22

RESUELTO: COMO SE ALGUNOS COMENTARIOS, UN FONELISTA VACÍO NO TENÍA CUANDO DEBIÓ HABER SIDO [].Rieles 3.1: idioma Ruby para evitar que cada uno arroje una excepción si es nulo?

¿Hay una manera de utilizar .each para que no se emite un error si el objeto es nulo o vacío (sin añadir una prueba adicional nulo/blanco?

Parece que si digo phonelist.each do |phone| que si phonelist es vacía, entonces el bloque no debe ser ejecutado.

Pero en mi opinión (haml) tengo - @myvar.phonelist.each do |phone| y si phonelist está vacía, se lanza una NoMethodError.

me encuentro con esto muchas veces, y siempre solucionar por agregar una verificación/rama explícita para .blank? pero parece que debe haber una e Otra manera de decirlo: cada uno de los medios vacíos no hace nada.

+2

Llamar a 'each' en un enumerable vacío simplemente no debe hacer nada. –

+1

@AndrewMarshall pero eso no es lo que está sucediendo, está llamando 'each' on' nil'. –

+1

@AndrewMarshall: quiso decir un objeto 'nil', no una colección vacía. –

Respuesta

15

Está tratando de golpear una curita en un problema mayor.

Ruby tiene un concepto de nil; no puedo evitarlo Si llama a un método en nil, está asumiendo que es válido, es decir, su diseño supone que es válido. Entonces, la pregunta realmente es: ¿dónde está el agujero en su diseño? ¿Por qué tu suposición es incorrecta?

El problema aquí no es que no pueda llamar a métodos arbitrarios en un objeto que no lo admite; el problema es que se supone que sus datos son válidos cuando obviamente ese no es siempre el caso.

Pero en mi opinión (haml) tengo - @ myvar.phonelist.each do | phone | y si la fonnista está vacía, arroja un NoMethodError.

No. Si phonelistno es un objeto que implementa .each se genera un error. Muy diferente.

Siempre puede inicializarlo en una matriz vacía si es nulo, es decir, phonelist ||= [], pero preferiría un diseño que garantice datos válidos siempre que sea posible.

42

Puede usar el método try para llamar .each a nil para que no arroje un error si el objeto es nulo o está vacío.

phonelist = nil 
phonelist.try(:each){|i| puts i} 
+1

Supongo que no entiendo por qué las personas recurren a algo así cuando sería óptimo simplemente asegurarse de que algo que nunca debería ser nulo no sea nulo. Si eso no se puede hacer (por el motivo que sea), ¿por qué haría esto en lugar de una simple declaración if? No lo entiendo –

+8

Estoy de acuerdo en que sería óptimo para garantizar que nunca obtendrá un cero, pero no veo por qué agregar una instrucción if es una mejor solución que usar try. Cualquiera de los enfoques debería hacer el trabajo. – johnnyx25

+0

Porque una declaración 'if' es más clara y más simple. –

26

Simplemente haga lo siguiente:

Array(phonelist).each do |phone| 
    #deal with your phone 
end 

Array (my_variable) asegurará para devolver una matriz si my_variable es nula.

No crea una nueva matriz si my_variable ya es una matriz, por lo que es seguro y liviano utilizarla donde quiera.

+1

Me gusta. Simple y elegante – idrinkpabst

1

Si obtiene phonelist de un hash (por ejemplo, un archivo JSON analizado), es posible que desee utilizar fetch con [] como valor predeterminado.

phonelist = my_data.fetch('phonelist', []) 
Cuestiones relacionadas