Una muestra de cómo se puede liar parda si este operador no se usa correctamente:
def modificar_central_nuclear(accion, opciones={})
opciones[:avisar_supervisor] ||= false
opciones[:efectuar_operacion] ||= true
puts opciones[:avisar_supervisor] ? "Se avisa supervisor de #{accion}" : "No se avisa supervisor de #{accion}"
puts opciones[:efectuar_operacion] ? "Se realiza accion #{accion}" : "No se realiza accion #{accion}"
end
- Esta función realiza una acción en una central nuclear recién inaugurada. Se establece como regla de negocio que siempre que se efectúe una operación, se debe avisar a un supervisor. Si no se realiza no hay que avisarlo (por ejemplo, cuando se hacen pruebas no hay que molestarle). En términos de código esto significa que en el hash opciones, los valores de :avisar_supervisor y :efectuar_operacion tendrán siempre el mismo valor en el momento de llamar a la función.
- También se indica que, como caso especial, si se llama a esta función sin opciones, hay que efectuar la acción pero no hay que avisar al operador.
>> modificar_central_nuclear(:subir_temperatura_core)Funciona bien. Ahora veamos el primer punto (suponemos q desde fuera de este código se cumple que se indican siempre las dos opciones y que estas tienen el mismo valor):
No se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
>> modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => true, :avisar_supervisor => true})Perfecto, somos unos cracks! Y ahora hacemos lo mismo pero no queremos bajar la temperatura ni avisar al operador (estamos probando que se crean logs recién introducidos p.ej):
Se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
>> modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => false, :avisar_supervisor => false})Ostras!! Parda habemus liada! Hemos subido la temperatura del core y encima sin avisar al supervisor... Evidentemente lo que esperábamos era que no se subiera la temperatura y que no se avisara al supervisor...
No se avisa supervisor de subir_temperatura_core
Se realiza accion subir_temperatura_core
=> nil
Veamos por qué pasa esto:
x ||= 'valor por defecto'La sentencia anterior asignará el valor 'valor por defecto' a la variable x si:
- La variable no existe (la crea y le asigna 'valor por defecto')
- La variable existe y su valor anterior es nil
- La variable existe y su valor anterior es false
Resumiendo: nunca de los jamases usar ||= con booleanos, especialmente si el valor anterior puede ser false. En el caso que nos ocupa es preferible hacer esto:
opciones[:efectuar_operacion] = true if opciones[:efectuar_operacion].nil?El código final quedaría:
def modificar_central_nuclear(accion, opciones={})Y ahora sí que obtenemos el resultado esperado:
opciones[:avisar_supervisor] = false if opciones[:avisar_supervisor].nil?
opciones[:efectuar_operacion] = true if opciones[:efectuar_operacion].nil?
puts opciones[:avisar_supervisor] ? "Se avisa supervisor de #{accion}" : "No se avisa supervisor de #{accion}"
puts opciones[:efectuar_operacion] ? "Se realiza accion #{accion}" : "No se realiza accion #{accion}"
end
>>modificar_central_nuclear(:subir_temperatura_core, {:efectuar_operacion => false, :avisar_supervisor => false})
No se avisa supervisor de subir_temperatura_core
No se realiza accion subir_temperatura_core
=> nil
No hay comentarios:
Publicar un comentario