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
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
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
> irb(main):016:1> end
> => FooBar
> irb(main):017:0> a.bar
> NoMethodError: undefined method `bar' for #
> 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
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