Where to declare project path for require


#1

Untill now whenever i made a script Id put all its files into a
directory along with any test files. When it came to requiring my own
files I could just do require “filename” as they were all in the same
place.

Now ive tried to create a directory structure that a lot of you pros use
such as

project
/bin
/lib
project.rb
/project
…any related files here
/tests
test.rb
/samples
…any stuff my tests may need e.g. offline webpages to scrape
etc

though im not planning on releasing any gems i just want a tidier
structure. however with this comes the headache of require.

At first i simply put this in my project.rb file at the top
$: << File.expand_path(File.dirname(FILE) + “/…/lib”)

and that made things ok
but then when i do tests what do i put in them? do i need to add
$: << File.expand_path(File.dirname(FILE) + “/…/lib”)
again or do i just do an include “/…/lib/project.rb” and let it declare
the new path??

ideally i want one place where i declare it and then forget all about
it. I have searched previous posts but none seem to mention what to do
in your test files. Any one help?


#2

ok ive been hacking away at this trying to figure out why its going
wrong but cant figure it out.

I understand about the loadpath and that require will go searching for
your required file in each of the specified directories and stop at the
first instance it finds.

If i have a three files
myproject/tests/test.rb

myproject/tests/samples/A.rb
myproject/tests/samples/B.rb

in test.rb :
require “samples/A”

in A.rb
require “B”

that should work shouldnt it??? but in my case it complains saying “no
such file B.rb”. IT should be able to find it because its in the same
diretory as A though.

Im going absolutely insane here. can anyone eplain why this is happening
and what how paths should be set with regards to your main project file
and test files etc


#3

Adam A. wrote:

but in my case it complains saying “no
such file B.rb”. IT should be able to find it because its in the same
diretory as A though.

No - all files are searched for relative to the $LOAD_PATH ($:) entries
only, not the directory which the file doing the requiring is in. Even
if you have “.” in $LOAD_PATH (meaning “current directory”), this refers
to the process’s current working directory, which is often not the same
as the dir the script is in.

I would do the following:

[myproject/tests/test-helper.rb]

This sets up all the paths we need

$:.unshift File.expand_path(File.dirname(FILE)+"/…/lib")
$:.unshift File.expand_path(File.dirname(FILE))

[myproject/tests/test.rb]
require File.dirname(FILE)+"/test-helper"
require ‘samples/A’

[myproject/tests/samples/A.rb]
require ‘samples/B’

The test-helper.rb file sets up absolute paths in $LOAD_PATH for all the
directories of interest. So the only thing that a top-level ruby app has
to do (one which is started directly from the command line) is to
require test-helper

The example here assumes you have

myproject/lib
myproject/tests

and adds these two directories to $LOAD_PATH. So if you do require
“samples/A” then it will look for /path/to/myproject/tests/samples/A.rb
and /path/to/myproject/lib/samples/A.rb

Note that samples/A.rb does require ‘samples/B’, because $LOAD_PATH
contains /path/to/myproject/tests (and not
/path/to/myproject/tests/samples)

By using absolute paths in $LOAD_PATH, it works regardless of which
directory you are in when you invoke the script. e.g.

set current working directory to /tmp

cd /tmp
ruby /path/to/myproject/tests/test.rb

Hope this is clear,

Brian.


#4

sorry for the late reply, i had a small break from programming.

Just want to thank you very much for your reply. It really has cleared
it all up for me and ended hours of frustration. Many thanks!


#5

I don’t know how it’s related to this topic but remember that with
ruby1.9 we get new require method, which IMHO is very importand:
require_relative “file”
(and as expected it require file relative to FILE)
With ruby1.8 (to be compatible) you can write own impl. of that
(stolen from
http://extensions.rubyforge.org/rdoc/classes/Kernel.html#M000039)
def require_relative(path)
require File.join(File.dirname(caller[0]), path.to_str)
end

I think it should be used very often by gem implementators. I don’t
like if someone modify $: to add some lib internal directories etc.


Pozdrawiam

Rados³aw Bu³at
http://radarek.jogger.pl - mój blog