I would like to see someone else do this. I’ve simplified the issue to
a small exercise. Given:
module MyEnhancement
def attr_accessor(*a)
put "doing something special with #{a.join(' ')}"
super(*a)
end
end
This module can be used in any class or module simply by using #extend.
class SomeClass
extend MyEnhancement
end
Great. However, I also want the end-user of this library to be able
effect all classes and modules with a single extend (or include) as
well, if they so choose. Eg.
class Module
include MyEnhancement
end
It would also be nice if the module’s methods can be made to work from
the toplevel (main):
extend MyEnhancement
Of course, these last two pieces of code do not work.
In attempting to implement this, I have found myself resorting to
unDRY, ugly, hacky code, that always seems to have a bug in it
somewhere. It’s infuriating. This is not how programming Ruby is
supposed to be!
Great. However, I also want the end-user of this library to be able
effect all classes and modules with a single extend (or include) as
well, if they so choose. Eg.
class Module
include MyEnhancement
end
Is the problem here that Module defines its own #attr_accessor
shadowing the new one?
It would also be nice if the module’s methods can be made to work from
the toplevel (main):
extend MyEnhancement
What should #attr_accessor do in the context of the toplevel object?
Maybe you can show us another example?
In attempting to implement this, I have found myself resorting to
unDRY, ugly, hacky code, that always seems to have a bug in it
somewhere. It’s infuriating. This is not how programming Ruby is
supposed to be!
Great. However, I also want the end-user of this library to be able
effect all classes and modules with a single extend (or include) as
well, if they so choose. Eg.
class Module
include MyEnhancement
end
I came up with this a while ago: inherit_from_self.rb · GitHub. It’s a
pretty
big hack but lets you write modules that override the behaviour of
classes
they’re mixed into.
Is the problem here that Module defines its own #attr_accessor
shadowing the new one?
Yes, that’s part of the issue here. In the case where one extends a
class, #super works, in the case of including it into Module, one had
to do the whole alias chaining thing.
As I worked on this it made me think that it would be nice if their
were a MetaKernel for the Module’s methods, just as there is a Kernel
for Object’s methods. That would at least DRY this part up.
It would also be nice if the module’s methods can be made to work from
the toplevel (main):
extend MyEnhancement
What should #attr_accessor do in the context of the toplevel object?
Maybe you can show us another example?
What it normally does, define a method wrapping an instance variable.
Having it at toplevel isn’t that important in this case. But I have a
similar case for an original method (#annotator) where it is.
If the toplevel object were a self extended module, this would not be
an issue either. I know I’ve brought this up more than a few times,
but I don’t recall Matz ever addressing it, and saying why it’s not a
good idea. Sure wish I knew, with all the meta-coding I’ve done this
is one of the few issues I keep bumping my head against.
In attempting to implement this, I have found myself resorting to
unDRY, ugly, hacky code, that always seems to have a bug in it
somewhere. It’s infuriating. This is not how programming Ruby is
supposed to be!
Hmm, I think this will be hacky indeed.
Unfortunately, what I’ve managed to get to work very much is. You can
see my hacks for the real deal here:
I ended up doing something similar to this. Though I wanted to use #super were I could so I created two versions of the attr_ overrides,
one with #super and one using #alias_method. I also overrode #append_features instead of using #included. You can see it here:
I came up with this a while ago:inherit_from_self.rb · GitHub. It’s a
pretty
big hack but lets you write modules that override the behaviour of
classes
they’re mixed into.
Sort of like a traits system?
I’m afraid I don’t know enough about traits and how they differ from
mixins
to be able to answer that. In fact, if you know of any good reference
material on traits I’d quite like to give it a read.
I’m afraid I don’t know enough about traits and how they differ from mixins
to be able to answer that. In fact, if you know of any good reference
material on traits I’d quite like to give it a read.
Sure, the cannonical text can be found here: http://www.iam.unibe.ch/~scg/Archive/PhD/schaerli-phd.pdf
I ended up doing something similar to this. Though I wanted to use #super were I could so I created two versions of the attr_ overrides,
one with #super and one using #alias_method. I also overrode #append_features instead of using #included. You can see it here:
Ah interesting, that would cover extend too, right?