ruby constants redefine redefinition

¿Cómo redefinir una constante de Ruby sin previo aviso?



constants redefine (4)

A menos que los valores de las constantes sean bastante extraños (es decir, si tiene constantes configuradas en nil o false ), la mejor opción sería usar el operador de asignación condicional: Tau ||= 2*Pi

Esto establecerá Tau en 2π si es nil , false o indefinido, y de lo contrario lo dejará solo.

Estoy ejecutando un código de Ruby que detecta un archivo de Ruby cada vez que cambia su fecha. En el archivo, tengo definiciones constantes, como

Tau = 2 * Pi

y, por supuesto, hacen que el intérprete muestre la advertencia de "constante ya inicializada" no deseada cada vez, así que me gustaría tener las siguientes funciones:

def_if_not_defined(:Tau, 2 * Pi) redef_without_warning(:Tau, 2 * Pi)

Podría evitar la advertencia al escribir todas mis definiciones constantes como esta:

Tau = 2 * Pi unless defined?(Tau)

pero es poco elegante y un poco húmedo (no DRY ).

¿Hay una mejor manera de def_if_not_defined ? ¿Y cómo redef_without_warning ?

-

Solución gracias a Steve:

class Object def def_if_not_defined(const, value) mod = self.is_a?(Module) ? self : self.class mod.const_set(const, value) unless mod.const_defined?(const) end def redef_without_warning(const, value) mod = self.is_a?(Module) ? self : self.class mod.send(:remove_const, const) if mod.const_defined?(const) mod.const_set(const, value) end end A = 1 redef_without_warning :A, 2 fail ''unit test'' unless A == 2 module M B = 10 redef_without_warning :B, 20 end fail ''unit test'' unless M::B == 20

-

Esta pregunta es vieja. El código anterior solo es necesario para Ruby 1.8. En Ruby 1.9, la respuesta de P3t3rU5 no produce ninguna advertencia y simplemente es mejor.


El siguiente módulo puede hacer lo que quieras. Si no puede proporcionar algunos consejos a su solución

module RemovableConstants def def_if_not_defined(const, value) self.class.const_set(const, value) unless self.class.const_defined?(const) end def redef_without_warning(const, value) self.class.send(:remove_const, const) if self.class.const_defined?(const) self.class.const_set(const, value) end end

Y como ejemplo de usarlo.

class A include RemovableConstants def initialize def_if_not_defined("Foo", "ABC") def_if_not_defined("Bar", "DEF") end def show_constants puts "Foo is #{Foo}" puts "Bar is #{Bar}" end def reload redef_without_warning("Foo", "GHI") redef_without_warning("Bar", "JKL") end end a = A.new a.show_constants a.reload a.show_constants

Da la siguiente salida

Foo is ABC Bar is DEF Foo is GHI Bar is JKL

Perdóname si he roto algún tabú de rubí aquí, ya que todavía me estoy preguntando algo sobre la estructura del Módulo: Clase: Eigenclass dentro de Ruby



Si desea redefinir un valor, entonces no use constantes, use una variable global en su lugar ($ tau = 2 * Pi), pero eso tampoco es una buena práctica. Debería convertirla en una variable de instancia de una clase adecuada.

Para el otro caso, Tau = 2 * Pi unless defined?(Tau) es perfectamente correcto y la más legible, por lo tanto, la solución más elegante.