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 ?

You should be able to do that by adapting this approach:

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

John M. 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 methodfoo’ for B:Class (NoMethodError)

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.

On Mon, Oct 28, 2013 at 4:31 PM, Joel P. [email protected]
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.

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

Robert K. 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.

On Tue, Oct 29, 2013 at 9:36 AM, Joel P. [email protected]
wrote:

Robert K. 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.

#!/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

What I did for convenience and easy read is:

module ModIncl
def whatever

end
end
module Mod
extend ModIncl
end

Now if I want to call a method without messing my class I can use
Mod.whatever. If I want to mess the methods into my class to call them
easily, then I do include ModIncl.

Not sure how @Robert K.'s answer made me think about this. I can
hardly comprehend what he does but thanks anyway.

On Tue, Oct 29, 2013 at 12:56 PM, Robert K.
[email protected] wrote:

heads up, Joel!
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

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

Cheers

robert