Feature #19277
Updated by georgeclaghorn (George Claghorn) almost 2 years ago
Refinements are a great way to isolate patches to the files that rely on them. Nonetheless, I believe the need to explicitly enable refinements in every file that uses them has hindered their adoption. As an inciting example, it’s hard to imagine Rails adopting refinements in their current form and requiring `using` calls for Active Support core extensions throughout Rails applications. I’d like to propose a middle way: allowing a Ruby project (a gem, library, application, etc.) to enable refinements for all of its Ruby files. This would combine the isolation benefits of refinements with the convenience of global monkey-patches. #### Projects To do this, we must decide how to identify projects and how they specify their desired refinements. A Ruby project is a directory containing a project configuration file with a special name. (I am intentionally not proposing a specific name for the file here. One will need to be chosen eventually, and suggestions are welcome.) A project configuration file is in Ruby format. When Ruby loads a script from a file, it searches upwards from the current directory for a project configuration file. For reasons of performance, project configurations may be cached per directory by project root path. The search for a project configuration would end when a configuration for a particular path prefix is found in the cache. When a project configuration is found, it is evaluated as though it were prepended to the beginning of the currently-loading file. Alternatively, a limited DSL could be provided to the configuration file that prepares interpreter state for the currently-loading file. Below is an example project configuration: ```ruby require "prestige/refinements" using Prestige::Refinements ``` For `ruby -e` and `irb`, the project configuration is searched for beginning from the current working directory. For `Kernel#eval`, the current file’s project configuration is used. #### Concerns * Performance, mainly. This is a significant amount of work to add to hot code paths. I believe the cost could be minimized with sensible caching, though not completely eliminated. I haven’t started implementing this and don’t have measurements of the actual cost yet. * Ergonomics. Is this the best way to provide project-scoped refinements? Is the project configuration format appropriate?