Issue #7240 has been updated by trans (Thomas Sawyer).


=begin
I have always thought module class methods should be included. Matz has stated his opposition to it b/c he sees it as a hindrance for some use cases, for example, internal methods spilling in when including the Math module. But I've always felt that those occurrences would always be easier to counteract (by just making a separate inner-module) if it were really necessary, than hacking around the limitations of the current behavior.

Short of changing the behavior of (({#include})), there are two other options. The first is to add another method like #include that does the deed. A good name for which is, as usual, hard to come up with. (Maybe (({#include!})) would be a viable option?) The other possibility is to allow class methods to be classified as inclusive or exclusive. By default module class methods would be exclusive, but using a keyword/method this could be changed in much the same way that methods are classed into public/private/protected.

For example:

    module M
      def self.foo; "foo"; end

      inclusive
      def self.bar; "bar"; end
    end
 
    module N
      include M
    end

    N.bar  => "bar"
    N.foo  => Error

I'm not sure I like this idea --I still think it would be better just to make it the usual behavior of (({#include})), but it is an option. 
=end

----------------------------------------
Feature #7240: Inheritable #included/#extended Hooks For Modules
https://bugs.ruby-lang.org/issues/7240#change-32051

Author: apotonick (Nick Sutterer)
Status: Open
Priority: Normal
Assignee: 
Category: 
Target version: 


An inheritable hook mechanism for modules would be a great way for module/gem authors to simplify their implementations.


The Problem
-----------

Let's say I have the following module.

  module A
    def self.included(base)
      # add class methods to base
    end
  end

So, A is overriding the #included hook to add class methods to base.

module B
  include A

  # class methods from A are here.
end

Since B is including A, A's #included method is invoked and A's class methods will be copied to B.

module C
  include B

  # class methods from B are lost.
end

When including B into C, B's #included is invoked and A's #included is lost. In our example, this means no class methods from A are in C.


Proposal
--------

It would be cool if #included/#extended in a module could be inherited to including descendants. I wrote a small gem "uber" that does this kind of stuff with a simple recursion. Roughly, it works like this.

  module A
    extend InheritableIncluded # "execute my #included everytime me or my descendents are included."

    def self.included(base)
      # add class methods to base
    end
  end

Now, A's #included is invoked every time it or a descending module is included. In our example, class methods from A would be around in C.

When discussing this with Matz we agreed that this might be really useful in Ruby itself. I'm just not sure how to mark inheritable hooks.


-- 
http://bugs.ruby-lang.org/