Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to redefine a Ruby constant without warning?

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.

like image 449
Eldritch Conundrum Avatar asked Jul 30 '10 21:07

Eldritch Conundrum


People also ask

What happens to a constant which is not assigned Ruby?

Ruby Constants Referencing an uninitialized constant produces an error.

How do you write a constant in Ruby?

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.

Are constants global in Ruby?

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.


1 Answers

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

like image 54
Steve Weet Avatar answered Sep 17 '22 15:09

Steve Weet