From: Rick DeNatale Date: 2006-09-02T06:28:41+09:00 Subject: Re: [Q] How can I ask to which module a method belongs to? On 9/1/06, Markus Gaelli wrote: > Hi List, > > more questions from a Ruby-Newbie... > > Sam Roberts from Ruby-Core answered to my original question: > >> I am aware of Singleton Methods, but as they can extend instances, > >> (how) can I extend classes without changing their original class > >> definition in Ruby? > >> > > > > This is probably best posted to ruby-talk, not ruby-core, folks would > > likely be quite interested. > > > > classes are "open" in ruby, you can add methods as you wish. > > > > irb(main):001:0> s = "hi" > > => "hi" > > irb(main):002:0> class String; def this(opt) puts(self+opt) end end > > => nil > > irb(main):003:0> s.this(" that") > > hi that > > => nil > > irb(main):004:0> "bye".this(" that") > > bye that > > => nil > > > > Cheers, > > Sam > > That is good news to me. But now I wonder, if and how I can ask e.g. > String#this(opt) in which module it is defined. First note, that a method can be defined in a module or a class, and that a class is a kind of module. I haven't tested this extensively but I think it works. It searches for a method name in a class the same way that methods are found at runtime, at each level of the class hierarchy, the class is searched, then any modules that class includes in the reverse order they were included. This code depends on Module#included_modules giving it's result in the right order, which a few quick tests seems to indicate: module A end module B end module C include B include A end C.included_modules => [A, B] module D include A include B end D.included_modules => [B, A] Okay so here's my code: class Module def module_defining(method_name) method_name = method_name.to_s return self if instance_methods(false).include?(method_name) included_modules.each do |mixin| answer = mixin.module_defining(method_name) return answer if answer end nil end end class Class def module_defining(method_name) answer = super return answer if answer return superclass.module_defining(method_name) if superclass end end irb(main):001:0> load 'moddefining.rb' => true irb(main):002:0> String.module_defining('==') => String irb(main):003:0> String.module_defining('id') => Kernel irb(main):004:0> String.module_defining('map') => Enumerable -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/