Hello,
It appears that including module A inside another module B can cause
problems for classes that have already included A. What seems to
happen is that a class can only see the methods from module B if that
class include module A before module A includes module B.
For example,
module A
def a
puts "a"
end
end
module B
def b
puts "b"
end
end
class C
include B
def c
puts "c"
end
end
module B
include A
def b2
puts "b2"
end
end
C.new.c
C.new.b
C.new.b2
C.new.a
produces
tolsen@neurofunk:~/svn/limeade$ /var/tmp/tst.rb
c
b
b2
/var/tmp/tst.rb:42: undefined method `a' for #<C:0x2ac204fe7180>
(NoMethodError)
Notice I can define b2() after C has already included B but including
A into B does nothing for C.
Any idea what's going on here?
Thanks,
Tim
on 2007-05-29 17:22
on 2007-05-29 18:25
On 2007-05-29, Tim Olsen <tolsen718@gmail.com> wrote: > It appears that including module A inside another module B can cause > problems for classes that have already included A. What seems to > happen is that a class can only see the methods from module B if > that class include module A before module A includes module B. It's a known problem that is apparently almost impossible to fix. See http://eigenclass.org/hiki/The+double+inclusion+problem . Unless there's been some development that I've failed to Google up, your only option is "Don't Do That!". :-( Unless Ruby 1.9 handles things better. Regards, Jeremy Henty
on 2007-05-29 19:05
On May 29, 12:25 pm, Jeremy Henty <onepo...@starurchin.org> wrote: > On 2007-05-29, Tim Olsen <tolsen...@gmail.com> wrote: > > > It appears that including module A inside another module B can cause > > problems for classes that have already included A. What seems to > > happen is that a class can only see the methods from module B if > > that class include module A before module A includes module B. > > It's a known problem that is apparently almost impossible to fix. Seehttp://eigenclass.org/hiki/The+double+inclusion+problem. Also know as the "Dynamic Inclusion Problem" or just the "Inclusion Problem". > Unless there's been some development that I've failed to Google up, > your only option is "Don't Do That!". :-( Unless Ruby 1.9 handles > things better. While, it would be great if someone did find a way, from what I understand its too difficult to fix given how Ruby works, so don't hold your breath. T.
on 2011-01-06 07:18
Well, this limitation can be circumvented by runnning the following
after each change in MyModule:
ObjectSpace.each_object(Module) do |m|
if m <= Enumerable
m.module_eval("include MyModule")
end
end
In order to understand the drawbacks of this solution, I suggest reading
http://ola-bini.blogspot.com/2007/07/objectspace-to-have-or-not-to-have.html
on 2011-01-20 10:28
Update: the aforementioned solution was encapsulated into a gem which
makes it feels like it were part of the Ruby language.
Synopsis:
Enumerable.module_eval { retroactively_include MyModule }
At http://rubygems.org/gems/retroactive_module_inclusion one may find
the link to the GitHub repository, documentation, bug tracker, etc.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.