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?