From: "David A. Black" Date: 2009-02-20T22:42:47+09:00 Subject: Re: module include class/instance methods confusion!! Hi -- On Fri, 20 Feb 2009, Adam Wilson wrote: > I have been having trouble today with a module include in a Rails app. > The module file sits in the /lib folder. > > My problem, I worked out (which I have noticed before) is that I cannot > seem to access defined class methods in the module via the including > class. It seems that only instance methods are available. Let me > explain: > > module MyModule > def self.test > "class" > end > > def test > "instance" > end > end > > class MyClass > include MyModule > end > > class MyController > my_class = MyClass.new > > test1 = MyClass.test #=> gives an NoMethodError > test2 = my_class.test #=> works > end > > Is there something I am missing here? Please note I just wrote this code > quickly to show the idea, have not tested! > Its not essential but seems a bit silly that I need to use an instance > method in a situation when a class method would be much neater. > > Any pointers much appreciated! If you have a spare six months, you can look through the previous discussions of this topic on this list :-) Basically, the module and the class that includes it are independent agents, when it comes to their own singleton/class methods. The include operation is for the benefit of the objects that already consult the class for methods: it adds the module to the method lookup path of those objects. The class object itself is unaffected. You can intercept the include event, though, and manipulate the lookup path of the class object itself. A very common pattern is: module M def x puts "Instance method" end module ClassMethods def y puts "Class method" end end def self.included(c) c.extend(ClassMethods) end end class C include M end C.new.x # Instance method C.y # Class method The idea here is to extend (i.e., do a per-object include) the class object itself with a specialized module, M::ClassMethods, at the same time that the module M is included in the class. The name "ClassMethods", of course, is arbitrary; the methods defined in that module are instance methods of the M::ClassMethods module. They only become "class methods" by virtue of the extend operation. I know it probably seems like a lot of work for something that you might think should be automatic, but it's actually good that it isn't automatic, because that would remove the ability to keep the singleton (class) methods of a given module and a given class separate. This way, with the out-of-the-box behavior being the more basic, there's nothing you can't do. David -- David A. Black / Ruby Power and Light, LLC Ruby/Rails consulting & training: http://www.rubypal.com Coming in 2009: The Well-Grounded Rubyist (http://manning.com/black2) Ruby Training Atlanta! April 1-3, http://www.entp.com/training/atlanta09