I'm using active_admin and I have a directory admin in app in a Rails 3 app with the declarations of models and pages. Every now and then I also have a class and when that class has a constant, like this:
class Foo
BAR = "bar"
end
then, I get this warning in every request that has to re-load some code in my Rails app:
/Users/pupeno/helloworld/app/admin/billing.rb:12: warning: already initialized constant BAR
Any ideas what's going and how to avoid these warnings?
class A
TEST = "foo"
end
puts A::TEST
# foo
class A
TEST = "bar"
end
# (irb): warning: already initialized constant TEST
puts A::TEST
# bar
In Ruby, you can open a class anytime and redeclare whatever is inside it. It raises a warning only for constants, but it does go ahead and make the change though.
Let's even re-write that code a bit more terse:
class A
TEST = "foo"
TEST = "bar"
end
# (irb):3: warning: already initialized constant TEST
The warning appears even if you're not really changing the constant, but just setting it to the same value.
class A
TEST = "foo"
TEST = "foo"
end
# (irb):3: warning: already initialized constant TEST
So overall its just a warning that can be safely ignored.
During Development, Rails reloads whatever changed code in your app. Newer versions of Rails are also pretty smart in figuring out which files have actually changed, and then reloads only those files. So assume you have this controller:
class TestController < ApplicationController
FOO = "bar"
def index
...
end
end
If you make any change inside this, this file will get reloaded. When the file is reloaded, FOO = "bar"
is parsed again, and you end up getting the same warning.
If you're using Rails 3.0 or 3.1, try the active_reload gem and see if your warning goes away (it might unload your classes before reloading them, which might cause the warning to go away)
Use the following to define constants:
FOO = "bar" unless const_defined?(:FOO)
This will define the constant only if it is not already present. So you will avoid the warnings.
Use a helper method to define constants and automate this
module ConstDefiner
def define_constant(name, value)
const_set(name, value) unless const_defined?(name)
end
end
ActionController::Base.send :extend, ConstDefiner
ActiveRecord::Base.send :extend, ConstDefiner
# Now in all your controllers/models:
# instead of FOO = "value" unless const_defined?(:FOO), use:
define_constant :FOO, "value"
These warnings happen only in Development mode. You won't be needing all the unless const_defined?(:FOO)
in production. Its generally not recommended to have development-specific code in production (unless its really really essential)
Remember that when you say FOO = "bar" unless const_defined?(:FOO)
, then even if you really make a change to the FOO
constant, it won't get reloaded once its defined. You'll have to stop and start rails server in order to reload it. But the probability of modifying constants during development is a little low when compared to actual code, and not something very frequent. As already said, this doesn't affect production code in any way.
Edit: Added link to active_reload gem
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