Including a module in an included module

module M1; end
module M2; include M1; end
module M1; DOG = :woof; end
module M2; DOG; end
# => :woof

I can add to a module after it has been included. Neat.

module M1; DOG = :woof; end
module M2; include M1; end
module M3; include M2; end
module M3; DOG; end
# => :woof

Including a module seems to give me any modules that it includes. Swish.

module M2; end
module M3; include M2; end
module M1; DOG = :woof; end
module M2; include M1; end
module M3; DOG; end
# => NameError: uninitialized constant M3::DOG

So I assumed I’d be able to include a module in a module after it has
been included, if you get my drift. It surprises me that this dog
doesn’t bark.

Prince N. wrote:

module M1; end
module M2; include M1; end
module M1; DOG = :woof; end
module M2; DOG; end
# => :woof

I can add to a module after it has been included. Neat.

module M1; DOG = :woof; end
module M2; include M1; end
module M3; include M2; end
module M3; DOG; end
# => :woof

Including a module seems to give me any modules that it includes. Swish.

module M2; end
module M3; include M2; end
module M1; DOG = :woof; end
module M2; include M1; end
module M3; DOG; end
# => NameError: uninitialized constant M3::DOG

So I assumed I’d be able to include a module in a module after it has
been included, if you get my drift. It surprises me that this dog
doesn’t bark.

The results seem to speak for themselves: include only unwraps the
namespace name from the names that were in the module at the time the
module was included–subsequently adding constants to the previously
included module does not present them unwrapped.

7stud – wrote:

The results seem to speak for themselves: include only unwraps the
namespace name from the names that were in the module at the time the
module was included–subsequently adding constants to the previously
included module does not present them unwrapped.

Nope. That rule doesn’t work with example 1. It appears one level of
nesting is required for my rule to hold true.

2009/8/18 Prince N. [email protected]:

module M3; include M2; end

=> NameError: uninitialized constant M3::DOG

So I assumed I’d be able to include a module in a module after it has
been included, if you get my drift. It surprises me that this dog
doesn’t bark.

Inclusion apparently works by extracting the ancestors of a module at
inclusion time and placing them in the ancestor chain of the class:

irb(main):001:0> module A
irb(main):002:1> def foo; “foo”; end
irb(main):003:1> end
=> nil
irb(main):004:0> A.ancestors
=> [A]
irb(main):005:0> class C
irb(main):006:1> include A
irb(main):007:1> end
=> C
irb(main):008:0> C.ancestors
=> [C, A, Object, Kernel, BasicObject]
irb(main):009:0> C.new.foo
=> “foo”
irb(main):010:0> module B
irb(main):011:1> def bar; “bar”; end
irb(main):012:1> end
=> nil
irb(main):013:0> module A
irb(main):014:1> include B
irb(main):015:1> end
=> A
irb(main):016:0> A.ancestors
=> [A, B]
irb(main):017:0> C.ancestors
=> [C, A, Object, Kernel, BasicObject]
irb(main):018:0> C.new.bar
NoMethodError: undefined method bar' for #<C:0x100de5c0> from (irb):18 from /opt/bin/irb19:12:in
irb(main):019:0> class C
irb(main):020:1> include A
irb(main):021:1> end
=> C
irb(main):022:0> C.ancestors
=> [C, A, B, Object, Kernel, BasicObject]
irb(main):023:0> C.new.bar
=> “bar”
irb(main):024:0>

As you can see, you can fix that by reincluding the module.

Kind regards

robert