I'm running some Ruby code which evals a Ruby file every time its date changes. In the file, I have constant definitions, like
Tau = 2 * Pi
and, of course, they make the interpreter display the unwanted "already initialized constant" warning every time, so, I'd like to have the following functions:
def_if_not_defined(:Tau, 2 * Pi) redef_without_warning(:Tau, 2 * Pi)
I could avoid the warning by writing all my constant definitions like this:
Tau = 2 * Pi unless defined?(Tau)
but it is inelegant and a bit wet (not DRY).
Is there a better way to def_if_not_defined
? And how to redef_without_warning
?
--
Solution thanks to 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
--
This question is old. The above code is only necessary for Ruby 1.8. In Ruby 1.9, P3t3rU5's answer produces no warning and is simply better.
Ruby Constants Referencing an uninitialized constant produces an error.
How to Define Constants. A constant doesn't require any special symbol or syntax to declare. You just need to make the first letter an uppercase letter.
Although constants look like local variables with capital letters, they have the visibility of global variables: they can be used anywhere in a Ruby program without regard to scope.
The following module may do what you want. If not it may provide some pointers to your solution
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
And as an example of using it
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
Gives the following output
Foo is ABC Bar is DEF Foo is GHI Bar is JKL
Forgive me if i've broken any ruby taboos here as I am still getting my head around some of the Module:Class:Eigenclass structure within Ruby
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With