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
on 02.07.2007 03:51
on 02.07.2007 10:09
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 02.07.2007 10:33
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 Gutteridge Bioinformatics Center Kyoto University
on 02.07.2007 11:10
<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
on 02.07.2007 18:07
Hi, Axel Etzold 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 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 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