# Making "require" just work with some dynamic load path manip

**URL:** <https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038>\
**Category:** Ruby\
**Created:** [March 7, 2007, 5:51pm UTC](https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038 "2007-03-07T17:51:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 7, 2007, 5:51pm UTC](https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038/1 "2007-03-07T17:51:10Z")

</div>

The problem:

If I have a simple file, “a.rb”:

```
#!/usr/bin/env ruby
require 'b'

```

And it’s companion, “b.rb”:

```
puts "Hello, world!"

```

Running “a.rb” works fine if I start from the directory containing  
those files. If I change to another directory, however, I get a  
LoadError because Ruby doesn’t know how to find “b.rb”.

Workarounds:

1. Set or modify the RUBYLIB environment variable so that Ruby knows  
which additional locations to search.
2. Manipulate the load path ($:) from within the program itself.

These workarounds are fine for me because I understand the quirks of  
Ruby’s load path. But I am looking for a way to make this stuff just  
work automatically for other users who don’t necessarily understand  
Ruby’s load path and will expect “a” to be able to find “b” because  
they’re in the same directory, no matter what the current working  
directory is at the time.

The solution:

So I already have a solution for this based on workaround “2” and I  
wanted to get some feedback on whether this is a good idea or not. The  
basic idea is to make a “custom\_require” method which does the  
following:

1. Try requiring the file normally.
2. On a LoadError, try adding the directory containing the file to the  
load path (only if it’s not already present).
3. Now try requiring it again.
4. If you get a second LoadError then put the load path back the way  
it was and re-raise the original error.
5. If you succeed then put the load path back the way it was anyway.

So here’s the basic code to do this. I try to make it as conservative  
as possible by making the modifications to the load path temporary,  
and always adding absolute paths so as to minimize the likelihood of  
the same file being evaluated twice. The security of dynamically  
modifying the load path is not really a concern because the users  
running this scripts already have full write access to them anyway and  
can therefore already do whatever they want, and they (and nobody  
else) have full control over the directories in which the scripts are  
stored.

To use the new method you would do:

```
custom_require 'b', __FILE__

```

The second parameter is necessary (as far as I can tell) because I  
know of no other clean way for the “custom\_require” method (itself in  
a different file) to know which file was being evaluated when the call  
to “custom\_require” was made.

What I’d like to know is, is there a better way?

```
def custom_require(file, fallback)
  begin
    require file
  rescue LoadError => e
    candidate = Pathname.new(fallback).dirname.realpath
    if $:.any? { |path| Pathname.new(path).realpath == candidate

```

rescue false }  
raise e  
else  
begin  
$:.push(candidate)  
status = require file  
rescue LoadError  
raise e  
ensure  
$:.pop  
status  
end  
end  
end  
end

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 7, 2007, 10:02pm UTC](https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038/2 "2007-03-07T22:02:59Z")

</div>

Is there a reason you are not using setup.rb and/or gems?

T.

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 8, 2007, 3:00am UTC](https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038/3 "2007-03-08T03:00:45Z")

</div>

On 7 mar, 22:01, “Trans” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Is there a reason you are not using setup.rb and/or gems?
> 
> T.

Neither of those is really appropriate because the files “a.rb” and  
“b.rb” are dynamically generated and probably not very long lived (the  
typical cycle will be: generate, use, throw away) and definitely not  
worth installing permanently. The thing that generates those files is  
actually distributed as a gem so there are no problems at that level;  
I just want the generated files to be as easy to use for end users as  
possible.

Cheers,  
Greg

---

<div class="post-metadata">

**Author:** ![greg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/71c47a/32.png) [@greg](https://www.ruby-forum.com/u/greg)\
**Post date:** [March 8, 2007, 3:10am UTC](https://www.ruby-forum.com/t/making-require-just-work-with-some-dynamic-load-path-manip/88038/4 "2007-03-08T03:10:45Z")

</div>

On Mar 7, 2007, at 6:00 PM, Greg H. wrote:

> I just want the generated files to be as easy to use for end users as  
> possible.
> 
> Cheers,  
> Greg

IF you want to garauntee to require b in the same dir as a you can  
do this:

# a.rb

puts “in a.rb”  
require File.join(FIle.dirname( **FILE** ), ‘b’)

# b.rb

puts “in b.rb”

Cheers-

– Ezra Z.  
– Lead Rails Evangelist  
– removed\_email\_address@domain.invalid  
– Engine Y., Serious Rails Hosting  
– (866) 518-YARD (9273)
