Given a User class:
class User
end
I want to define a new constant using .class_eval. So:
User.class_eval { AVOCADO = 'fruit' }
If I try to access it via
User::AVOCADO, I getuninitialized constant User::AVOCADO, butUser.const_get(:AVOCADO)works. Why?If I define a constant inside a Rails Concern in the
includedmethod and include the concern in theUserclass, I can access it via the regular::lookup. For instance:
module FruitConcern
extend ActiveSupport::Concern
included do
AVOCADO = 'fruit'
end
end
class User
include FruitConcern
end
User::AVOCADO
=> 'fruit'
However, looking up the source code for ActiveSupport::Concern, included just stores that block in an instance variable (@_included_block), and then it's override of append_features will call base.class_eval(&@_included_block).
So, if it's just calling User.class_eval with the same block, why User::AVOCADO works when the constant is defined inside that included block, but not when I call User.class_eval { AVOCADO = 'fruit' } directly?
- Weirdly (see this blog post), when doing
User.class_eval { AVOCADO = 'teste' }, it seems Ruby also leaks the constant to the top level. So:
User.const_get(:AVOCADO)
=> "fruit"
AVOCADO
=> 'fruit'
I know blocks have flat scopes, but the constant was NOT defined beforehand, and I expected class_eval to change both self and the default definee to the receiver. What is going on here? And how is this constant being defined twice, at the top-level and also in the User scope?