From: "Jesús Gabriel y Galán" Date: 2009-12-05T08:59:29+09:00 Subject: Re: Use of extend from within a Class On Sat, Dec 5, 2009 at 12:37 AM, Mike Papper wrote: > I would like to include a module into a 'static' class - such that all > the modules methods are class methods. One basic way to do this is to have the class extend the module: irb(main):017:0> module Z irb(main):018:1> def test; "testZ"; end irb(main):019:1> end => nil irb(main):020:0> class C irb(main):021:1> extend Z irb(main):022:1> end => C irb(main):023:0> C.test => "testZ" > The problem is that code in the > module that uses "self.class.XYZ' breaks and when this code is included, > ruby cannot find the XYZ method. > > Here is an example: > > module Basic >  def methoda >    puts "AAAAAAAAAAA" >  end > >  def mb >    self.class.cee This is wrong. self.class is Class, and the Class class doesn't have a method "cee". >  end > >  module ClassMethods >    attr_writer :cee > >    def cee >      puts "CCCCCCCCCCCCC" >    end >  end > end I think you are confusing this usage. The name ClassMethods is a convention used to denote a set of methods that will be added to the class as class methods when you include this module. This is usually done as: module Test module ClassMethods def test; "test"; end end def self.included mod mod.extend ClassMethods end end If you simply want a method defined in the singleton class of your module do: module Basic def self.cee "CCCCCCC" end end If you want to call it from a method of the module: module Basic def mb Basic.cee end def self.cee "CCCCC" end end If you then want mb to be a class method of the classes you choose, you can use extend instead of include: irb(main):045:0> module Basic irb(main):046:1> def mb irb(main):047:2> Basic.cee irb(main):048:2> end irb(main):049:1> def self.cee irb(main):050:2> "CCCCCCCCCCCCC" irb(main):051:2> end irb(main):052:1> end => nil irb(main):053:0> class YY irb(main):054:1> extend Basic irb(main):055:1> end => YY irb(main):056:0> YY.mb => "CCCCCCCCCCCCC" > I think my understanding of modules and using extend (or include) is > faulty or at least doesnt cover the subtleties of when a modle uses > "self.class" and its included in another class, then what becomes of > self.class in this case?? You can ask Ruby :-) irb(main):036:0> module Basic irb(main):037:1> def mb irb(main):038:2> puts self irb(main):039:2> end irb(main):040:1> end => nil irb(main):041:0> class XX irb(main):042:1> extend Basic irb(main):043:1> end => XX irb(main):044:0> XX.mb XX So, how it works is that when a class extends a module, the methods get added to the singleton class of the class. This means that the method is now in the lookup path of the class methods. But (and this is the same with the normal inheritance) self inside those methods is still the original object that received the method call, so in this case the class XX. Another example: irb(main):058:0> class Class irb(main):059:1> def test_class; puts self; end irb(main):060:1> end => nil irb(main):061:0> XX.test_class XX This is with simple inheritance (XX inherits from Class). With extended modules it's the same, as shown above. Basically: 1.- extend includes the methods in that module to the singleton class of the receiving object. 2.- classes are objects 3.- so when a class extends a module, the module instance methods (is that the correct way to refer to those?) get added to the singleton class of the class (commonly known as class methods). This stuff is tricky, and I don't know if I explained myself very well, so please ask if there's something not clear enough. Hope this helps, Jesus.