How to temporarily change the required path in Ruby ($ :)?

I am doing some tricks with a bunch of Rake tasks for a complex project, gradually solving a bit of complexity in pieces at a time. This revealed a strange network of dependencies left by the previous project developer.

What I would like to do is add a specific path to the project to the require list of search paths, aka $: However, I only need the path that needs to be searched in the context of one particular method. Now I am doing something like this:

 def foo() # Look up old paths, add new special path. paths = $: $: << special_path # Do work ... bar() baz() quux() # Reset. $:.clear $: << paths end def bar() require '...' # If called from within foo(), will also search special_path. ... end 

This is clearly a monstrous hack. Is there a better way?

+4
source share
2 answers

require is actually a method, it is Kernel#require (which calls rb_require_safe ) so that you can at least do your hacking in the headless version. If you like such a thing.

  • The orignal alias requires a path
  • If an absolute path is passed, call the original require method
  • Iterate over the loading path by creating an absolute path and calling the original require method.

Just for fun, I had a quick bash, the prototype of which is below. This is not fully verified, I have not tested the semantics of rb_require_safe , and you will probably also need to look at #load and #include for completeness - and this remains a patch of the Kernel monkey. Perhaps this is not entirely monstrous, but it is certainly a hack. Your call if it is better or worse than messing with the global variable $:

 module Kernel alias original_require require # Just like standard require but takes an # optional second argument (a string or an # array of strings) for additional directories # to search. def require(file, more_dirs=[]) if file =~ /^\// # absolute path original_require(file) else ($: + [ more_dirs ].flatten).each do |dir| path = File.join(dir, file) begin return original_require(path) rescue LoadError end end raise LoadError, "no such file to load -- #{file}" end end end 

Examples:

 require 'mymod' require 'mymod', '/home/me/lib' require 'mymod', [ '/home/me/lib', '/home/you/lib' ] 
0
source

Since $: is an array, you have to be careful what you do. You need to take a copy (via dup ) and replace later. It is easier to just delete what you added:

 def foo $: << special_path # Do work ... bar() ensure # Reset. $:.delete(special_path) end 

Without additional information, it is difficult to find out if there is a better way.

+3
source

Source: https://habr.com/ru/post/1307889/


All Articles