Add Object#preextend to ActiveSupport

Sometimes we’d like to monkey patch some classes/modules from external libraries for many reasons including bug fixes until a new library version is released or maybe we need to change the default behavior of some class. For instance, the active_record_migrations gem will allow migrations to be used as an independent project and it supports changing the default location for the migrations from “db/migrate” to something else. But “db/migrate” is hard coded in some method:

That means the only option for active_record_migrations is to

override “create_migration_file” by copying the original implementation and allowing the path to be customized: A bit ugly and fragile solution, I know, but I can’t think of another option since my PR has been ignored in the last months but it doesn’t matter for what I’m requesting. This is just an example to demonstrate that sometimes we’re forced to monkey patch some classes to support some features. For this particular case no monkey patch was required and inheritance was used instead but in other cases we don’t have this option. In such cases having something like Object#preextend could be helpful in how we manage such patches by isolating them in separate modules. Instead of reopening a class to change some class method we could add the alternative implementation in a separate module and call #preextend in a similar way we do with prepend. I’ve requested this feature to Ruby itself and Boris came with a simple enough implementation that maybe could be added to ActiveSupport if you agree: Suggested implementation by Boris Stitnicky: Pretty simple, right? module LibraryImpl def self.library_method ‘original impl’ end end module MyPatch def library_method original_impl = super “#{original_impl} => patched impl” end end LibraryImpl.preextend MyPatch assert LibraryImpl.library_method == ‘original impl => patched impl’ What do you think?

I think this motivation can be summarized as: #prepend has use cases, in particular for singleton classes.

I don't see this in AS. AS is defined as a fine balance:

    * Ruby extensions key for Rails core development.

    * Ruby extensions experience proves to be really really       helpful/common in web development.

Add to that a few rule exceptions due to historical reasons, and you get AS.

In that sense AS has a different goal than facets, say.

In this particular case, I don't see preextend fits into that definition, and as you saw this is nothing but prepending in the singleton class.

I would use plain Ruby until the Ruby language defines something like this itself.

Ok, Xavier, thanks, but I had to try it :slight_smile: