Modules and class methods

Why does this not work!

···

########################################
module Foo
     def self.foo a
  puts a
     end
end

class Bar
    include Foo
    foo "hello"
end

foo.rb:20: undefined method `foo' for Bar:Class (NoMethodError)
####################################

but this does

class Bar
    def self.foo a
  puts a
     end
    foo "hello"
end

What am I misunderstanding about modules???

--
Brad
http://xtargets.com

There are a few alternatives, the clearest one IMO being:

module Foo
   def foo a # note no self.
      puts a
   end
end

class Bar
   extend Foo # note extend, _not_include
   foo "hello"
end

The other option is to augment the include procedure. Ruby provides a hook
Module#included.

module Foo
    def self.included(including_class_or_module)
       class << including_class_or_module
          def foo a
             puts a
          end
       end
   end
end

class Bar
   include Foo
   foo "hello"
end

Usually when people do this and a module contains both singleton methods and
instance methods it will look something like:

module Foo
   def inst_meth1
   end

   def inst_meth1
   end

   module ClassMethods
       def foo a
          puts a
       end
  end

  def self.included(other)
     other.extend ClassMethods
  end
end

class Bar
  include Foo
  foo "hello"
end

Finally, you can of course use classes and plain old inheritance:

class Foo
   def self.foo a
      puts a
   end
end

class Bar < Foo
   foo "hello"
end

···

On 5/4/07, Brad Phelan <phelan@tttech.ttt> wrote:

Why does this not work!

########################################
module Foo
     def self.foo a
        puts a
     end
end

class Bar
    include Foo
    foo "hello"
end

foo.rb:20: undefined method `foo' for Bar:Class (NoMethodError)
####################################

but this does

class Bar
    def self.foo a
        puts a
     end
    foo "hello"
end

What am I misunderstanding about modules???

--
Brad
http://xtargets.com

Module inclusion does not include singleton methods.

Brad Phelan wrote:

Why does this not work!

########################################
module Foo
    def self.foo a
    puts a
    end
end

class Bar
   include Foo
   foo "hello"
end

foo.rb:20: undefined method `foo' for Bar:Class (NoMethodError)
####################################

but this does

class Bar
   def self.foo a
    puts a
    end
   foo "hello"
end

What am I misunderstanding about modules???

--
Brad
http://xtargets.com

The below code obviously work the way I wish

module Foo
    def foo
       puts "a"
    end
end

class Bar
    extend Foo
    puts foo
end

however is there any way to get the same effect by using include. I would like to mix in class and instance methods in one call. It seems
I can do one or the other but not both at the same time. Is that
correct?

···

--
Brad Phelan
http://xtargets.com

Hi --

Brad Phelan wrote:

Why does this not work!

########################################
module Foo
    def self.foo a
    puts a
    end
end

class Bar
   include Foo
   foo "hello"
end

foo.rb:20: undefined method `foo' for Bar:Class (NoMethodError)
####################################

but this does

class Bar
   def self.foo a
    puts a
    end
   foo "hello"
end

What am I misunderstanding about modules???

--
Brad
http://xtargets.com

The below code obviously work the way I wish

module Foo
  def foo
     puts "a"
  end
end

class Bar
  extend Foo
  puts foo
end

however is there any way to get the same effect by using include. I would like to mix in class and instance methods in one call. It seems
I can do one or the other but not both at the same time. Is that
correct?

Basically, yes: mixing in a module inserts the module in only one
method lookup path, and a class and its instances generally have very
different lookup paths.

You can use the inherited hook in Module to do both -- for example:

   module M
     def self.included(c)
       m = self
       c.class_eval { extend m }
     end

     def meth
       puts "here"
     end
   end

   class C
     include M
   end

   C.meth # here
   C.new.meth # here

David

···

On Fri, 4 May 2007, Brad Phelan wrote:

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black\)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf\)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)

You can use the inherited hook in Module to do both -- for example:

  module M
    def self.included(c)
      m = self
      c.class_eval { extend m }
    end

    def meth
      puts "here"
    end
  end

  class C
    include M
  end

  C.meth # here
  C.new.meth # here

David

Now that is the sneaky little hook I was looking for.

Thanks

Brad

···

--
http://xtargets.com