Forum: Ruby Nested Mixin Problem(?)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Vasco A. (Guest)
on 2007-07-02 05:51
Hi,

could someone check and comment if this is something that i don't
understand well or a ruby "somehow" problem? please

Here's the code:

module A
  def a; :a; end
end

module B
  include A
  def b; :b; end
end

module C
  def c; :c; end
end

class D
  include B
end

D.new.a #=> :a     ## Ok for me
D.new.b #=> :b     ## Ok for me

module B
  include C
end

D.new.c #=> NoMethodError: undefined method `c' for #<D:0xb7cb985c>  ##
This is not ok for me.

Thanks,
Vasco Andrade e Silva
Axel E. (Guest)
on 2007-07-02 12:09
(Received via mailing list)
Dear Vasco,

it seems like you wanted to include something before it is
defined.
The following worked for me:

module A
  def a; :a; end
end

module B
  include A
  def b; :b; end
end

module C
  def c; :c; end
end

module B  #   <------  interchanged these
  include C
end

class D        # <------ interchanged these
  include B
end

D.new.a #=> :a     ## Ok for me
D.new.b #=> :b     ## Ok for me


p D.new.c  #=>:c   ## Ok for you?


Best regards,

Axel
Alex G. (Guest)
on 2007-07-02 12:33
(Received via mailing list)
On 2 Jul 2007, at 10:51, Vasco Andrade e Silva wrote:

>
>   include B
> 0xb7cb985c>  ##
> This is not ok for me.
>
> Thanks,
> Vasco Andrade e Silva
>
> --
> Posted via http://www.ruby-forum.com/.
>

I think you've found an interesting edge case for modules and mixins.
Redefining a module only seems to work to one 'level'. So this works:

irb(main):001:0> module FooBar
irb(main):002:1> end
=> nil
irb(main):003:0> class Baz
irb(main):004:1> include FooBar
irb(main):005:1> end
=> Baz
irb(main):006:0> a = Baz.new
=> #<Baz:0x330568>
irb(main):007:0> module FooBar
irb(main):008:1> def foo; :foo; end
irb(main):009:1> end
=> nil
irb(main):010:0> a.foo
=> :foo

But not here (analogous to your example I think):

irb(main):011:0> module Bar
irb(main):012:1> def bar; :bar; end
irb(main):013:1> end
=> nil
irb(main):014:0> module FooBar
irb(main):015:1> include Bar
irb(main):016:1> end
=> FooBar
irb(main):017:0> a.bar
NoMethodError: undefined method `bar' for #<Baz:0x330568>
         from (irb):18

We need a guru to explain why...

Alex G.

Bioinformatics Center
Kyoto University
Robert D. (Guest)
on 2007-07-02 13:10
(Received via mailing list)
<snip>
> irb(main):016:1> end
> => FooBar
> irb(main):017:0> a.bar
> NoMethodError: undefined method `bar' for #<Baz:0x330568>
>          from (irb):18
>
> We need a guru to explain why...
That is definitely not me, but there was a very interesting thread by
Tom (aka Trans) very recently and Pit provided a nice metaprogramming
tool to address the issue which is called "double inclusion". [ Sorry
I am bad at finding references to threads :( ]

As a matter of fact there is an easy way to update the method lookup
chain
just continue as follows in your irb session:

irb(main):019:0> class Baz
irb(main):020:1> include FooBar # Play it again Sam
irb(main):021:1> end
=> Baz
irb(main):022:0> a.bar
=> :bar

It has something to do with the proxies that are created for included
modules, maybe a Guru will explain this in detail.

Cheers
Robert
Vasco A. (Guest)
on 2007-07-02 20:07
Hi,

Axel E. wrote:
> it seems like you wanted to include something before it is
> defined.

No. I wanted to use mixins for more than 'one level', as Alex G.
explain it:
>I think you've found an interesting edge case for modules and mixins.
>Redefining a module only seems to work to one 'level'. So this works:
> ...

I didn't know that this "problem" was called "double inclusion" (thanks
Robert) or "Dynamic Module Include Problem". After a quick search for
"double inclusion" you get:
http://eigenclass.org/hiki/The+double+inclusion+problem
http://www.ruby-forum.com/topic/112897

If some Guru come along and see this thread maybe he/she could give a
more indepth answer.

Meanwhile...
Thank you guys,
Vasco
This topic is locked and can not be replied to.