From: "alexeymuranov (Alexey Muranov)" Date: 2012-10-31T18:02:17+09:00 Subject: [ruby-core:48651] [ruby-trunk - Feature #7240] Inheritable #included/#extended Hooks For Modules 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/