Interesting (and useful!) behavior for how constants are looked up when multiple modules are included into a class. Constants within modules are prioritized over the included modules themselves.
module Namespace
class Foo
end
end
module Mixins
module Foo
end
end
class Base
include Namespace
include Mixins::Foo
p Foo
end
# => Namespace::Foo
This behavior prevents constant name shadowing when you include a module, but still want to access a class of the same name.
@postmodern One of the stranger things about Ruby for me is how constant lookup is scoped.
@postmodern I remember spending quite a while working out how this all worked when I wrote https://github.com/freerange/method_log
e.g. this spec: https://github.com/freerange/method_log/blob/ab50a74b951e756dd6e7bed86f746961971d7c31/spec/method_finder_spec.rb#L226
Fun times!
@postmodern but including the module doesn't define that module's name on the includer at all:
module Mixins
module Foo
end
end
class Base
include Mixins::Foo
p Foo
end
NameError: uninitialized constant Base::Foo
@postmodern Also, only tangentially related but there is a thing I stumbled across with inclusion that I find weird. Short version:
module A
module B
module C
end
end
include B
end
module A
module D
C # NameError - I'd expect this to resolve as A::C
end
end
Explored in more depth, and using the names I was using when I encountered it, rather than the obtuse single letters, here: https://gist.github.com/notEthan/f3a2909aa414158762911cedade30c08
@ethan @postmodern nice gist but I’ve to admit all that behavior looks completely expected to me