Inheriting class methods from modules / mixins in Ruby

mixins, ruby

Solution

A common idiom is to use `included` hook and inject class methods from there.

module Foo
  def self.included base
    base.send :include, InstanceMethods
    base.extend ClassMethods
  end

  module InstanceMethods
    def bar1
      'bar1'
    end
  end

  module ClassMethods
    def bar2
      'bar2'
    end
  end
end

class Test
  include Foo
end

Test.new.bar1 # => "bar1"
Test.bar2 # => "bar2"

Problem

It is known that in Ruby, class methods get inherited: ``` class P def self.mm; puts 'abc' end end class Q < P; end Q.mm # works ``` However, it comes as a surprise to me that it does not work with mixins: ``` module M def self.mm; puts 'mixin' end end class N; include M end M.mm # works N.mm # does not work! ``` I know that #extend method can do this: ``` module X; def mm; puts 'extender' end end Y = Class.new.extend X X.mm # works ``` But I am writing a mixin (or, rather, would like to write) containing both instance methods and class methods: ``` module Common def self.class_method; puts "class method here" end def instance_method; puts "instance method here" end end ``` Now what I would like to do is this: ``` class A; include Common # custom part for A end class B; include Common # custom part for B end ``` I want A, B inherit both instance and class methods from `Common` module. But, of course, that does not work. So, isn't there a secret way of making this inheritance work from a single module? It seems inelegant to me to split this into two different modules, one to include, the other to extend. Another possible solution would be to use a class `Common` instead of a module. But this is just a workaround. (What if there are two sets of common functionalities `Common1` and `Common2` and we really need to have mixins?) Is there any deep reason why class method inheritance does not work from mixins?

Original source

Related problems