Issue #7240 has been updated by alexeymuranov (Alexey Muranov).


=begin
trans (Thomas Sawyer) wrote:

> 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. 


I think that there would be issues with "including" methods defined on the module itself.  For example:

  module M
    # ...
  end

  class C
    include! M
  end

Now, which methods defined of M can be called on C?  Only those from the meta-class of M?  Those from the meta-class of M and from the ancestors of the meta-class?  All public?  All?  I cannot come up from the top of my mind with a (({Module})) public methods which is not defined in (({Class})), but there are at least private ones, for example: should (({C.send(:module_function, :f)})) work after the inclusion in the above example?

To me, a possible solution seems to be to have a second method table in modules (i suggested above to define such methods as singleton methods on some object returned by some private method named, for example, (({Module#base}))). The inclusion method could be still called (({include})) as it would not conflict with the current usage.

To state completely my current point of view, meta-class looks to me like hack, and inheriting (({Class})) from (({Module})) does not look as a very good idea :).
=end

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

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/