# Special super call for module class-level inclusion

**URL:** <https://www.ruby-forum.com/t/special-super-call-for-module-class-level-inclusion/113206>\
**Category:** Ruby\
**Created:** [August 28, 2007, 6:51pm UTC](https://www.ruby-forum.com/t/special-super-call-for-module-class-level-inclusion/113206 "2007-08-28T18:51:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [August 28, 2007, 6:51pm UTC](https://www.ruby-forum.com/t/special-super-call-for-module-class-level-inclusion/113206/1 "2007-08-28T18:51:55Z")

</div>

Since I’ve come upon the issue again, I reckon, it’s as good time as  
any to put this in the air.

The issue, again, is that module class methods are not  
“inherited” (for lack of a better word). In the past I’ve argued for  
this, but it has been consistently argued down due to the extraneous  
methods it would add to classes. However, it occurs to me that the  
core problem that I continually face for the lack of this, it simply  
that I can’t call super in a class level method and expect it to move  
through included module methods. The reason this is such a problem, it  
that it makes it very difficult to create an “inheriting variable”.  
This is the reason Facets contains inheritor.rb, but even that is  
limited to only simple cases.

To make this clear, here is a simple example of the idea:

class X  
include M  
def self.foo  
[‘Xfoo’]  
end  
end

module M  
def self.foo  
[‘Mfoo’] + super  
end  
end

class Y \< X  
include M  
def self.foo  
[‘Yfoo’] + super  
end  
end

Y.foo #=\> [‘Yfoo’, ‘Xfoo’]

As you can see there is no ‘Mfoo’ in the list.

If your’re wondering how this is useful, consider any use-case where  
meta-information needs to associated to a method. Just as methods are  
inherited so too their meta-information. Possible uses are annotations  
and pre, post, around wraps.

So the thought I had today is that rather then full inclusion at the  
class-level, that we might simply have an alternate #super call that  
would traverse the include modules class methods as well as classes. I  
realize that might be tricky to implement, but it would satisfy the  
need without all the unwanted baggage.

T.

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [August 30, 2007, 1:58am UTC](https://www.ruby-forum.com/t/special-super-call-for-module-class-level-inclusion/113206/2 "2007-08-30T01:58:53Z")

</div>

Trans wrote:

> The issue, again, is that module class methods are not  
> “inherited” (for lack of a better word). In the past I’ve argued for  
> this, but it has been consistently argued down due to the extraneous  
> methods it would add to classes. However, it occurs to me that the

IMHO the reason for this problem is that modules serve double duty as  
both mixins (instance methods) and namespaces (class methods).

> core problem that I continually face for the lack of this, it simply  
> that I can’t call super in a class level method and expect it to move  
> through included module methods. The reason this is such a problem, it  
> that it makes it very difficult to create an “inheriting variable”.  
> This is the reason Facets contains inheritor.rb, but even that is  
> limited to only simple cases.

The problem piqued my interest so despite my best attempts at  
self-control I wound up writing code for it :-/

class Module  
attr\_accessor :class\_methods\_module  
def class\_methods(&block)  
self.class\_methods\_module ||= begin  
mod = Module.new  
core = (class \<\< self; self; end)  
prev = core.method(:included)  
core.send(:define\_method, :included) do |into\_class|  
prev.call(into\_class)  
into\_class.extend(mod)  
end  
mod  
end  
class\_methods\_module.class\_eval(&block)  
end  
end

class Class  
def class\_methods(&block)  
instance\_eval(&block)  
end  
end

module M  
def a;“Ma”;end  
class\_methods do  
def b;“Mb”;end  
end  
end

class C  
include M  
def a;“Ca”+super;end  
class\_methods do  
def b;“Cb”+super;end  
end  
end

puts C.new.a #=\> CaMa  
puts C.b #=\> CbMb

---

<div class="post-metadata">

**Author:** ![Trans](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/t/dfb087/32.png) [@Trans](https://www.ruby-forum.com/u/Trans)\
**Post date:** [August 31, 2007, 5:20pm UTC](https://www.ruby-forum.com/t/special-super-call-for-module-class-level-inclusion/113206/3 "2007-08-31T17:20:04Z")

</div>

On Aug 29, 4:58 pm, Daniel DeLorme [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> core.send(:define_method, :included) do |into_class|
> 
> ```
> 
> def class\_methods(&block)  
> instance\_eval(&block)  
> end  
> end

Nice work! That’s not the easiest piece of meta-code to write. But has  
been touched on before. Facets has had a version of this for a while  
now, used extensively by Nitro/Og, written primarily by Daniel  
Schierbeck. It looks like this:

class Module

alias\_method :append\_features\_without\_class\_extension, :append\_features

def class\_extension(&block)  
@class\_extension ||= Module.new do  
def self.append\_features(mod)  
append\_features\_without\_class\_extension(mod)  
end  
end  
@class\_extension.module\_eval(&block) if block\_given?  
@class\_extension  
end

private :class\_extension

def append\_features(mod)  
append\_features\_without\_class\_extension(mod)  
mod.extend(class\_extension)  
if mod.instance\_of? Module  
mod. **send** (:class\_extension). **send** (:include,  
class\_extension)  
end  
end

end

class Class  
undef\_method :class\_extension  
end

Your definition of Class’s method is an interesting idea and may make  
a good adjustment Facets’ undef\_method.

On the downside, this approach doesn’t RDoc well --actually it doesn’t  
RDOc at all. Also, many people seem put off by the general aesthetic  
of it too.

As of late I’ve been leaning toward the idea of the old ClassMethods  
module solution, but modifying #include (or a similar new method) to  
handle the extension rather than using the included callback.  
(Personally, I’d also prefer a better name than ClassMethods, but  
that’s of minor consequence).

T.
