# Managing "requires" in projects with many subdirectories

**URL:** <https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011>\
**Category:** Ruby\
**Created:** [January 3, 2007, 12:50am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011 "2007-01-03T00:50:38Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 3, 2007, 12:50am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/1 "2007-01-03T00:50:38Z")

</div>

I’d like to know how people people managing their file dependencies  
with projects with several directories. Described below is the  
problem, and a demo of a possible rudimentary solution for which I’d  
like feedback/discussion. (I’ve searched and can’t find any notes for  
handling requires elegantly. It could be that I’m searching in the  
wrong place … please point me in the right direction if yes)

I’ve been working on a small project with several directories. Using  
the $:.unshift File.join( ( File.expand\_path( File.dirname( **FILE** )  
) ), ‘…’, ‘…’, ‘blah’ ) trick gets pretty boring to type, doesn’t do  
much for the code readability, and doesn’t help when files get moved  
around.

Side note: As a relic of my C++ interest, I also like my requires to be  
self-contained so my files are independent (e.g., if A uses B and C,  
I’ll require B and C in A, even if B requires C … that way, if the  
require ‘C’ is removed from B, A will still work).

Here’s the quick demo of one possible solution for handling requires  
for a project with multiple subdirectories:

## in root:

\*\* File add\_dirs\_to\_search\_path.rb:

```
require 'find'
Find.find( File.expand_path( File.dirname( __FILE__ ) ) ) do |path|
  if FileTest.directory?(path)
    $:.unshift path
  end
end

```

## in root/A:

\*\* File a\_thing.rb:

```
module A
  class AThing; def go() "A go!"; end; end
end

```

## in root/B:

\*\* File a\_client.rb:

```
require 'a_thing'
module B
  class BThing; def go() "B go: #{A::AThing.new.go}"; end; end
end

```

## Back in root:

\*\* File main.rb:

```
$:.unshift File.expand_path( File.dirname( __FILE__ ))
require 'add_dirs_to_search_path'
require 'a_client'

b = B::BThing.new
puts b.go

```

Result when called from root:

$ ruby main.rb  
B go: A go!

Notes, advantages, drawbacks:

- Module names mimic the directory structure (per the code conventions  
at RWiki)

- B only has to use "require ‘a\_thing’, since a\_thing’s directory was  
pushed into the include search path

- Any code that uses B must now have specified the search path to  
a\_thing.rb somehow, either using the -I command-line directive, an  
implicit require (requiring some code that requires A), or by requiring  
add\_dirs\_to\_search\_path.rb

- main has to have “$:.unshift File.expand\_path( File.dirname( **FILE**  
)); require ‘add\_dirs\_to\_search\_path’”. So would any test suite, etc.

- Directory changes are easily handled. You can move A::AThing to a  
different directory (note that this change should probably be  
accompanied by a change in module name, per RWiki code conventions)

- To disambiguate the desired file, include the directory. For  
example, if root/C also contains a file a\_thing.rb, and you wanted to  
use _that_ file in main, you’d change the require in main to “require  
File.join( ‘C’, ‘a\_thing.rb’ )”.

- The require gets mixed up if different folders with the same name  
contain files with the same name. For example, if there’s another file  
A/C/a\_thing.rb, and the module definition matches the directory  
structure (module A; module C; class AThing; …), the require _can_  
bomb since the wrong file might be included.

- in add\_dirs\_to\_search\_path.rb, I’m dynamically finding the files, but  
you could also hardcode them:

This whole idea might be kind of silly … it might be better to be  
explicit when including files (like you have to do in Java … “import  
com.x.my.utilities.rock.Thingy”), and to always fully specify modules  
whenever you’re referring to a class.

Sorry for the long post - but I’d like to hear any good strategies for  
managing requires. Thanks,

Jeff

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 3, 2007, 3:41am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/2 "2007-01-03T03:41:00Z")

</div>

On Jan 2, 2007, at 15:50, removed\_email\_address@domain.invalid wrote:

> ```
> Find.find( File.expand_path( File.dirname( __FILE__ ) ) ) do | 
> 
> ```
> 
> path|  
> if FileTest.directory?(path)  
> $:.unshift path  
> end  
> end

This’ll work great right up until you have something like myproj/  
time.rb and you also need time.rb from stdlib.

Instead, use explicit paths like everybody else does, it’ll be less  
confusing.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)

I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 3, 2007, 4:17am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/3 "2007-01-03T04:17:04Z")

</div>

removed\_email\_address@domain.invalid wrote:

> much for the code readability, and doesn’t help when files get moved
> 
> ```
> end
> 
> ```
> 
> in root/B:  
> Back in root:
> 
> at RWiki)  
> )); require ‘add\_dirs\_to\_search\_path’". So would any test suite, etc.
> 
> - The require gets mixed up if different folders with the same name  
> ‘b’,  
> com.x.my.utilities.rock.Thingy"), and to always fully specify modules  
> whenever you’re referring to a class.
> 
> Sorry for the long post - but I’d like to hear any good strategies for  
> managing requires. Thanks,

You mention a root/ so that makes me think you’re running directly from  
your work directory. It’s much easier to organize your project into a  
standard layout and then use setup.rb to reinstall between coding  
cycles. See [setup.rb User Manual](http://i.loveruby.net/en/projects/setup/doc/). You could  
also use RubyGems in this manner, but it is not as convenient when  
coding.

Having said that I do have a lib that does the trick – I’ve had it for  
a while, but I haven’t quite finsihed tweaking it out for release (I’m  
adding a remote require feature to it). But it works fine for the most  
part, and I sure could use another’s input to get it to final release  
state. If you (or anyone else) is interested let me know.

T.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 4, 2007, 5:59am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/4 "2007-01-04T05:59:51Z")

</div>

Eric H. wrote:

> This’ll work great right up until you have something like myproj/time.rb  
> and you also need time.rb from stdlib.
> 
> Instead, use explicit paths like everybody else does, it’ll be less  
> confusing.

Like everybody else except rails… which adds about 41 entries to the  
$LOAD\_PATH 😛

Daniel

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 4, 2007, 1:52pm UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/5 "2007-01-04T13:52:46Z")

</div>

On Jan 3, 2007, at 10:59 PM, Daniel DeLorme wrote:

> Eric H. wrote:
> 
> > This’ll work great right up until you have something like myproj/  
> > time.rb and you also need time.rb from stdlib.  
> > Instead, use explicit paths like everybody else does, it’ll be  
> > less confusing.
> 
> Like everybody else except rails… which adds about 41 entries to  
> the $LOAD\_PATH 😛

And I believe the salted login generator for Rails once had the exact  
conflict Eric describes.

James Edward G. II

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 4, 2007, 9:58am UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/6 "2007-01-04T09:58:08Z")

</div>

On 1/3/07, Eric H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > 
> 
> Instead, use explicit paths like everybody else does, it’ll be less  
> confusing.

I agree with Eric. We used to add all directories recusively to the  
search path, and used relative paths without directories. It was nice  
and all but:

- you need to keep the filenames unique. I was bitten by this when  
suddenly I used a filename of a file from unrelated project, that got  
on the search path somehow (it was located in the parent directory of  
my stuff). It took me some time until I realized what’s going on.

- if you give the code to another person, he/she can’t tell from the  
source where is the required file located. he/she has to figure out by  
serching the whole tree.

- if you mix these two approches, you may and up with some files  
required more times, which may or may not be good.

Now I’m slowly going back to requires with relative paths to ‘lib’  
directory, that gets on the search path from the main file or command  
line.

NB: in the  
$:.unshift File.join( File.expand\_path( File.dirname( **FILE** )) ,  
‘…’, ‘…’, ‘blah’ )  
I would reverse expand\_path and join, to remove those … elements, i.e.  
$:.unshift File.expand\_path( File.join( File.dirname( **FILE** ),  
‘…’, ‘…’, ‘blah’ ))

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 6, 2007, 7:30pm UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/7 "2007-01-06T19:30:57Z")

</div>

On Jan 4, 2007, at 17:10, removed\_email\_address@domain.invalid wrote:

> and then the command line becomes:
> 
> $ ruby -Ipath/to/lib my\_file.rb ?

At worst I use ruby -Ilib my\_file. Rarely is it way over there in  
path/to. (When it is, I set up a rake rule.)

> The reason I ask is that you still need to pull in the path/to/lib  
> somewhere, and including it in the -I param means that subsequent devs  
> will need to know this (yes, I know it’s minor, but I’d want others to  
> be able to cd to /tests and just write “ruby ts\_all.rb”, or “ruby  
> tc\_specific\_test\_case.rb” in any subdirectory … trying to make life  
> easy for them, cause I’m such a great guy).

Nobody needs to remember anything if you write it down in a rake  
rule. Automate, automate, automate.

PS: the Test::Unit convention is tests live in test/ and  
implementations live in lib/ and test files start with test\_. This  
makes working with the standard tools (like testrb) and  
interoperating with other tools (like rake and ZenTest) a breeze.

> Also, minor point, but path separators are different in different OSs,  
> aren’t they?

Ruby is smart enough to do what you mean.

–  
Eric H. - removed\_email\_address@domain.invalid - [http://blog.segment7.net](http://blog.segment7.net)

I LIT YOUR GEM ON FIRE!

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [January 6, 2007, 7:17pm UTC](https://www.ruby-forum.com/t/managing-requires-in-projects-with-many-subdirectories/81011/8 "2007-01-06T19:17:59Z")

</div>

Thanks for the notes … one final question:

> Now I’m slowly going back to requires with relative paths to ‘lib’  
> directory, that gets on the search path from the main file or command  
> line.

Does this mean that your files would, say, look like this:

(file a.rb)  
require ‘some/thing’

and then the command line becomes:

$ ruby -Ipath/to/lib my\_file.rb ?

The reason I ask is that you still need to pull in the path/to/lib  
somewhere, and including it in the -I param means that subsequent devs  
will need to know this (yes, I know it’s minor, but I’d want others to  
be able to cd to /tests and just write “ruby ts\_all.rb”, or “ruby  
tc\_specific\_test\_case.rb” in any subdirectory … trying to make life  
easy for them, cause I’m such a great guy).

Also, minor point, but path separators are different in different OSs,  
aren’t they? So don’t you need to do something like:

(file a.rb)  
require File.join(‘some’, ‘thing’)

which also becomes tiresome? Or does the ruby interpreter take care of  
that? Sorry, I don’t have another machine to try this out on, I only  
have 'doze.

> NB: in the  
> $:.unshift File.join( File.expand\_path( File.dirname( **FILE** )) ,  
> ‘…’, ‘…’, ‘blah’ )  
> I would reverse expand\_path and join, to remove those … elements, i.e.  
> $:.unshift File.expand\_path( File.join( File.dirname( **FILE** ),  
> ‘…’, ‘…’, ‘blah’ ))

Yes, that’s better, thanks.

Thanks for putting up with my inane questions.

jz
