rails/rails — pull request #13220 by shioyama (2013-12-07 03:01:10+00:00)
Title: [Proposal] Add capability to extend all relations on model with modules or block

Problem: We want to extend all relations on a given model with custom methods (add or override finders or factory methods, etc.) without monkeypatching `ActiveRecord::Relation` itself.

Currently it is possible to extend a relation with [`ActiveRecord::Relation#extending`](https://github.com/rails/rails/blob/17c29a0df0da5414570b025b642e90968e96cddc/activerecord/lib/active_record/relation/query_methods.rb#L788), e.g. `Post.all.extending(MyModule).where(...)`, and it is also possible to [extend association proxies with a block](https://github.com/rails/rails/blob/17c29a0df0da5414570b025b642e90968e96cddc/activerecord/lib/active_record/associations.rb#L444), which allows you to add custom methods to a given association on a given model.

Both of these entrypoints are too local for the case where we want to extend *all* relations on a given model. The only way to do this is to patch core AR methods such as AR::Relation#relation.

At least two gems do this: I wrote a patch in [Globalize](https://github.com/globalize/globalize) and @norman did something similar in [FriendlyId (v 4.x)](https://github.com/norman/friendly_id/tree/4.0-stable). Making the relation extensions work on associations as well requires yet more hacking (see e.g. norman/friendly_id#452).

The proposal here is the simplest way I can imagine to provide an entrypoint that avoids the need for such patching: a method (`extend_relation`) which accepts one or more modules and/or a block (just like `extending`), save those in a class attribute on the model itself, and then when creating relations always extend the relation with those modules. This works for associations as well.

cc @tenderlove