Hyperextended #
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.)
Cat-herder
I’ve tried to coax append_features into auto-extending with ClassMethods when present, but singleton methods defy wrapping. It is written.
Tim
Rails uses this extensively. It doesn’t have the module extend its own ClassMethods though, because they’re not intended to be used independently.
Thomas
Very cool :
) I tried to this myself some days ago and failed. Next time, I will search ruby-talk first ;)Ulysses
Hey, _why. The nice thing about the internal ClassMethods pattern is that it can be automated:
Somewhat ironic is that if you try to use a module to extend append_features (and thus avoid alias) it doesn’t work.
As an appendum, I should add that it is a good idea to use self::ClassMethods—if you just use ClassMethods, you might inherit ClassMethods from a parent scope, which could lead to some hard to figure out bugs.
(Sorry for rambling on,)
flgr
This ought to be possible with evil-ruby. Just do
class << self; inherit class << GiftedClass; self; end; end
—sorry that it looks so complex.clark
you must have eaten all meta kryptonite
why
Wow, yeah. Rails is all over this one. Haroomph.
Comments are closed for this entry.