Issue #7240 has been updated by Brian Katzung.


I'm a relatively new Ruby programmer so I may have missed some of the nuances, but I have written http://rubygems.org/gems/extended_include that I *believe* satisfies the original posting requirements.

In a nutshell:

~~~
require 'extended_include'

module A
  # ...
  include_class_methods # (module=ClassMethods, ...) -OR-
  include_class_methods do
    def cm; "Well I'll be a class method!!!"; end
  end
  # (A.extend Extended_Include to get ::included is automatic)
end

module B
  extended_include A # include + arrange to chain A's ::included (if present and base needs it) in ours
  def self.included (base) # Only if we need to do something beyond Extended_Import::included
    super base rescue nil # Let Extended_Include extend and chain
    # Do something more...
  end
end
~~~

If somebody more experienced would like to look it over, I would love some feedback.

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

* Author: Nick Sutterer
* Status: Feedback
* Priority: Normal
* Assignee: 
* Category: 
* Target version: next minor
----------------------------------------
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.



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