Ruby: Is it possible to define a class method in a module?

Ruby

Ruby Problem Overview


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 it 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.

Ruby Solutions


Solution 1 - Ruby

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

Solution 2 - Ruby

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

Solution 3 - Ruby

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.

Solution 4 - Ruby

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'

Solution 5 - Ruby

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMisha MoroshkoView Question on Stackoverflow
Solution 1 - RubyOmar QureshiView Answer on Stackoverflow
Solution 2 - RubyMladen JablanovićView Answer on Stackoverflow
Solution 3 - RubyErRoRView Answer on Stackoverflow
Solution 4 - RubyOliver ZeyenView Answer on Stackoverflow
Solution 5 - RubyKaushikView Answer on Stackoverflow