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


apotonick (Nick Sutterer) wrote:
> =begin
> Ah ok, now I understand you, Alexey. Instead of having a keyword (inclusive/inheritable) you want to have a special "namespace" as in
> 
>   module M
>     def to_be_inherited.m; end
> 
> which would include the class method #m when including M? Cool. However, how would we make self.included "inheritable" then?
> 
> > I wonder what the core developers would say.
> 
> I talked to Matz at the Sapporo RubyKaigi this year and he made me file this issue!
> =end

I am sorry, i used your thread to propose my own feature request in a sense, i have already corrected this with #7250.  I hoped that maybe there would be no need for inheritable `self.included` if "class-level includable" methods could be defined in a module, and if including one module in another would treat those methods appropriately.

"Inheritable self.included" seems a confusing concept for me, because modules do not inherit from one another.  I even think that including a module in a class and including a module in a module are different operations which maybe should have been called differently.

I propose roughly the following diagram and behavior:

module
  personal_singleton_methods
  includable_instance_methods
  includable_class_methods

class
  personal_singleton_methods
  instance_methods

object
  personal_singleton_methods

Writing

  module M; end
  module N
    include M
  end
  class C
    include N
  end

would result in having pointers

N.includable_instance_methods -> M.includable_instance_methods
N.includable_class_methods -> M.includable_class_methods

and hidden inheritance

C < N_proxy_for_C < M_proxy_for_C < An_ancestor_of_C

where N_proxy_for_C has N.includable_instance_methods for its own instance methods and has N.includable_class_methods for its own class methods.

These are rough ideas, i am not familiar with Ruby implementation details.
----------------------------------------
Feature #7240: Inheritable #included/#extended Hooks For Modules
https://bugs.ruby-lang.org/issues/7240#change-32088

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/