Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby modules and Module#append_features explanation

Lately I bumped into this very interesting post: http://opensoul.org/blog/archives/2011/02/07/concerning-activesupportconcern/ which walks through (and explains) the ActiveSupport::Concern source code.

A few questions arose, but the most important was this:

Obviously there's a method called append_features which (by the docs at least) says: "Ruby’s default implementation of this method will add constants, methods, and variables of this module to the base module".

I always thought that module works the same as classes in the sense of the method lookup chain - the only difference is that you can't instantiate objects from it, and that it's not defined as a 'superclass' of this class (since a module is not actually a class). meaning that when a class includes a module, the module is simply being added as a direct parent in the class's inheritance hierarchy, and as a result, methods which are missing in the including class, will be looked for at the module.

But if that's the case, then what does it mean that append_features actually "adds methods to the base module", which means that you can actually prevent this behaviour, by overriding this method (which ActiveSupport::Concern actually does).

Can someone create some order in my head?

like image 840
Mikey S. Avatar asked Jun 09 '13 06:06

Mikey S.


1 Answers

Basically, the append_features is - or should be considered - a deeply internal ruby method.

The Module.include method is defined (in the "eval.c" file with the name of rb_mod_include) as a loop, which just calls mod.append_features (and then mod.included) for every Module argument passed to it.

The default append_features implementation (rb_mod_append_features in "eval.c" file), calls the rb_include_module, and this is the method which does the real job.

(Actually the really real job is done by the include_modules_at few lines below)

It means that you are perfectly right saying that you can prevent or break this basic ruby functionality by overriding the append_features (at least if you don't call the super).

The ActiveSupport::Concern actually calls the super, just in some cases it postpones the actual call until the "concerned" module is included by some "non-concerned" one.

It's usually better to override the included method instead of append_features. The included is defined as just "return nil", thus the probability of breaking anything is smaller. And that is what the documentation of the included method advices.

like image 112
Arsen7 Avatar answered Oct 17 '22 00:10

Arsen7