Ruby: Is it possible to define a class method in a module?
Say there are three classes: A
, B
& C
. I want each class to have a class method, say self.foo
, that has exactly the same code for A
, B
& C
.
Is i开发者_StackOverflow社区t possible to define self.foo
in a module and include this module in A
, B
& C
? I tried to do so and got an error message saying that foo
is not recognized.
Yep
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def some_method
# stuff
end
end
end
One possible note I should add - if the module is going to be ALL class methods - better off just using extend ModuleName
in the Model and defining the methods directly in the module instead - rather than having a ClassMethods module inside the Module, a la
module ModuleName
def foo
# stuff
end
end
module Common
def foo
puts 'foo'
end
end
class A
extend Common
end
class B
extend Common
end
class C
extend Common
end
A.foo
Or, you can extend the classes afterwards:
class A
end
class B
end
class C
end
[A, B, C].each do |klass|
klass.extend Common
end
Rails 3 introduced a module named ActiveSupport::Concern
which has the goal of simplifying the syntax of modules.
module Foo
extend ActiveSupport::Concern
module ClassMethods
def some_method
# stuff
end
end
end
It allowed us to save a few lines of "boilerplate" code in the module.
This is basic ruby mixin functionality that makes ruby so special.
While extend
turns module methods into class methods, include
turns module methods into instance methods in the including/extending class or module.
module SomeClassMethods
def a_class_method
'I´m a class method'
end
end
module SomeInstanceMethods
def an_instance_method
'I´m an instance method!'
end
end
class SomeClass
include SomeInstanceMethods
extend SomeClassMethods
end
instance = SomeClass.new
instance.an_instance_method => 'I´m an instance method!'
SomeClass.a_class_method => 'I´m a class method'
Just wanted to extend Oliver's answer Define Class methods and instance methods together in a module.
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def a_class_method
puts "ClassMethod Inside Module"
end
end
def not_a_class_method
puts "Instance method of foo module"
end
end
class FooBar
include Foo
end
FooBar.a_class_method
FooBar.methods.include?(:a_class_method)
FooBar.methods.include?(:not_a_class_method)
fb = FooBar.new
fb.not_a_class_method
fb.methods.include?(:not_a_class_method)
fb.methods.include?(:a_class_method)
精彩评论