How can I use module methods as class methods?

Hi,

Here is a code :

module A
  def self.foo
      1
  end
  def bar
      2
  end
end

## Now if I do extend
class B
    extend A
end

B.bar # 2
B.foo # error
B.new.foo # error

## Now if I do include
class B
    include A
end

B.new.bar # 2
B.foo # error
B.new.foo # error

Any chance to get access or do like `B.foo` ?

···

--
Posted via http://www.ruby-forum.com/.

When you want to include Modules into a Class you would typically do

require filename # if you are using two different script

class B
    include A # => includes all methods in the Module
end

···

On Mon, Oct 28, 2013 at 10:37 AM, Love U Ruby <lists@ruby-forum.com> wrote:

Hi,

Here is a code :

module A
  def self.foo
      1
  end
  def bar
      2
  end
end

## Now if I do extend
class B
    extend A
end

B.bar # 2
B.foo # error
B.new.foo # error

## Now if I do include
class B
    include A
end

B.new.bar # 2
B.foo # error
B.new.foo # error

Any chance to get access or do like `B.foo` ?

--
Posted via http://www.ruby-forum.com/\.

--
John Moon

You should be able to do that by adapting this approach:
http://softwarebyjosh.com/2012/01/21/Pirating-Ruby-Methods-For-Fun-And-Profit.html

···

--
Posted via http://www.ruby-forum.com/.

John Moon wrote in post #1125888:

When you want to include Modules into a Class you would typically do

require filename # if you are using two different script

class B
    include A # => includes all methods in the Module
end

No it wouldn't :

module A
  def self.foo
      1
  end
  def bar
      2
  end
end

## Now if I do include
class B
    include A
end

B.new.foo # undefined method `foo' for #<B:0x17148f0> (NoMethodError)
B.foo # undefined method `foo' for B:Class (NoMethodError)

···

--
Posted via http://www.ruby-forum.com/\.

By defining self.foo you're explicitly saying that it belongs to module
A. If you wanted to include or extend a class with it you wouldn't use
"self".

The way to accomplish this is demonstrated with some metaprogramming
that I linked to in my previous response.

···

--
Posted via http://www.ruby-forum.com/.

The most straightforward approach that satisfies the thread subject
would be to use #extend.

module M
  def bar; 123 end
end

class X
  extend M
end

X.bar # => 123

Cheers

robert

···

On Mon, Oct 28, 2013 at 4:31 PM, Joel Pearson <lists@ruby-forum.com> wrote:

By defining self.foo you're explicitly saying that it belongs to module
A. If you wanted to include or extend a class with it you wouldn't use
"self".

The way to accomplish this is demonstrated with some metaprogramming
that I linked to in my previous response.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Robert Klemme wrote in post #1125970:

The most straightforward approach that satisfies the thread subject
would be to use #extend.

This was already covered in the initial post, he's using a module with
"self.foo", which doesn't work with extend since that method remains
with the module rather than transferring to the class.

···

--
Posted via http://www.ruby-forum.com/\.

Aargh! Overlooked that. Posting after midnight... Thank you for the
heads up, Joel!

My 2 Cents: I do not think it is a good idea to do what OP is trying
to do. After all methods defined on the module itself affect this
exact module's state. If one wants to provide some kind of
functionality that should be reusable by class instances then defining
a module with instance methods and extending the class would be the
proper way.

If there needs to be related behavior, i.e. instance methods using
class methods then I would use two modules. You can either act on the
extend event or on the #included event. I'd probably use the
#included callback as that stresses the fact that I want to provide
instance functionality.

#!/usr/bin/ruby -w

module Foo
  module Foo4Class
    def instance_count
      @instance_count
    end
  end

  def self.included(cl)
    cl.extend Foo4Class

    cl.instance_variable_set '@instance_count', 0

    cl.singleton_class.class_eval do
      def new(*a,&b)
        super.tap { @instance_count += 1 }
      end
    end
  end

  def shout_instance_count
    printf "There have been %d of us created!\n", self.class.instance_count
  end
end

class Bar
  include Foo
end

Array.new(10) { Bar.new }.each(&:shout_instance_count)

Kind regards

robert

···

On Tue, Oct 29, 2013 at 9:36 AM, Joel Pearson <lists@ruby-forum.com> wrote:

Robert Klemme wrote in post #1125970:

The most straightforward approach that satisfies the thread subject
would be to use #extend.

This was already covered in the initial post, he's using a module with
"self.foo", which doesn't work with extend since that method remains
with the module rather than transferring to the class.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

I have updated the gist with a more appropriate solution that reduces
meta programming in favor of ordinary methods.

Cheers

robert

···

On Tue, Oct 29, 2013 at 12:56 PM, Robert Klemme <shortcutter@googlemail.com> wrote:

On Tue, Oct 29, 2013 at 9:36 AM, Joel Pearson <lists@ruby-forum.com> wrote:

Robert Klemme wrote in post #1125970:

The most straightforward approach that satisfies the thread subject
would be to use #extend.

This was already covered in the initial post, he's using a module with
"self.foo", which doesn't work with extend since that method remains
with the module rather than transferring to the class.

Aargh! Overlooked that. Posting after midnight... Thank you for the
heads up, Joel!

My 2 Cents: I do not think it is a good idea to do what OP is trying
to do. After all methods defined on the module itself affect this
exact module's state. If one wants to provide some kind of
functionality that should be reusable by class instances then defining
a module with instance methods and extending the class would be the
proper way.

If there needs to be related behavior, i.e. instance methods using
class methods then I would use two modules. You can either act on the
extend event or on the #included event. I'd probably use the
#included callback as that stresses the fact that I want to provide
instance functionality.

Example for adding functionality to instances of a class which needs help from class methods of the same class. Use two modules - one for instance methods and one for class methods. · GitHub

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/