As you well know, mixins only copy plain instance methods into the target class. And may I ask what world-class solutions we have if you need to copy class methods? Um, you can’t copy the metaclass (which includes class methods.)
>> class GiftedClass
>> def self.capabilities
>> [:swimming, :diving, :chess, :valour]
>> end
>> end
>> class LesserClass
>> extend (class << GiftedClass; self; end)
>> end
TypeError: wrong argument type Class (expected Module)
from (irb):8:in `extend'
from (irb):8
I’ve been trying to write a hyperextend method that will take a class and mixin instance and class methods alike, but no.
Nobu’s three-year-old solution is to put all your class methods in a nested module, then alter append_features to allow the mixin to copy the nested module functions into the metaclass. And don’t forget to extend the original module, to make sure the nested module functions are still usable as class (module) methods in the original module.
module Mix
def inst_meth
puts 'inst_meth'
end
module ClassMethods
def class_meth
puts 'class_meth'
end
end
extend ClassMethods
def self.append_features(klass)
super
klass.extend(ClassMethods)
end
end
class LesserClass
include Mix
end
While the behind-the-scenes is a bit wordy, it’s excellent that you can still use include and get the class methods to come through. (Unearthed from ruby-talk:35979.)