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 Gutteridge
Bioinformatics Center
Kyoto University
···
On 2 Jul 2007, at 10:51, Vasco Andrade e Silva wrote:
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.
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
···
Alex Gutteridge
Bioinformatics Center
Kyoto University
--
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck
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 Gutteridge
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
If some Guru come along and see this thread maybe he/she could give a
more indepth answer.