metaprogramming/constant_lookup.rb
tests/_examples/metaprogramming/constant_lookup.rb in the metorex repository.
# Where a constant is found: the scopes a method was written in, then the
# ancestors of the innermost one, then Object and the modules it includes.
# A private constant is read only without its scope written out.
module Shared
RETRIES = 3
end
include Shared
module Settings
def self.retries
RETRIES
end
end
p(Settings.retries)
p(::RETRIES)
class Base
LIMIT = :from_base
end
Object::LIMIT = :from_object
class Derived < Base
def self.limit
LIMIT
end
end
p(Derived.limit)
class Lenient
def self.const_missing(name)
:"missing_#{name}"
end
def self.lookup
UNDEFINED_HERE
end
end
p(Lenient.lookup)
anonymous = Module.new do
def self.name
nil
end
def self.inspect
"#<Settings module>"
end
end
begin
anonymous::ABSENT
rescue NameError => error
p(error.message)
end
class Vault
SECRET = :hidden
private_constant :SECRET
def self.reveal
SECRET
end
def self.known
defined?(SECRET)
end
end
p(Vault.reveal)
p(Vault.known)
p(defined?(Vault::SECRET))
begin
Vault::SECRET
rescue NameError => error
p([error.message, error.name, error.receiver])
end
class Vault
class Inner
end
private_constant :Inner
end
begin
eval("class Vault::Inner; end")
rescue NameError => error
p(error.message)
end
begin
eval("def assigns\n LIMIT = 1\nend")
rescue SyntaxError => error
p(error.message.include?("dynamic constant assignment"))
end
class Object
HIDDEN_TOP = :top
private_constant :HIDDEN_TOP
end
p(HIDDEN_TOP)
begin
::HIDDEN_TOP
rescue NameError
p(HIDDEN_TOP)
end
Output:
3
3
:from_base
:missing_UNDEFINED_HERE
"uninitialized constant #<Settings module>::ABSENT"
:hidden
"constant"
nil
["private constant Vault::SECRET referenced", :SECRET, Vault]
"private constant Vault::Inner referenced"
true
:top
:top