# \_\_FILE\_\_ for requiring file

**URL:** <https://www.ruby-forum.com/t/file-for-requiring-file/74499>\
**Category:** Ruby\
**Created:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499 "2006-11-07T10:46:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/1 "2006-11-07T10:46:16Z")

</div>

Hello

I keep wondering if there is a way to have **FILE** be delayed  
in its evaluation. For example, in my tests cases, I usually do the  
following so that my test cases are imune to where they are run from:

class TestMyClass \< Test::Unit::TestCase

TEST\_DIR = File.dirname( **FILE** )  
DATA\_DIR = File.join(TEST\_DIR, “data”)

def data\_file(file)  
File.join(DATA\_DIR, file)  
end

def test\_xyz  
open(data\_file(“fred”))  
assert …  
end  
end

The problem is I have to add this to every test case since I can’t put  
data\_file inside a module and include it without also having o define  
TEST\_DIR as a constant of Object inside every testcase.

In other words, I don’t want to do:

TEST\_DIR = File.dirname( **FILE** )  
class TestMyClass \< Test::Unit::TestCase  
require ‘test\_helper’  
include TestHelper  
TestHelper.init **FILE**  
end

This just seems a bit verbose.

I guess what I need is something like: **REQUIRING\_FILE**  
so my TestHelper module could be written as:

module TestHelper  
TEST\_DIR = File.dirname( **REQUIRING\_FILE** )  
DATA\_DIR = …as above  
end

Has anyone ever needed such a thing? Is there a better way of solving  
this problem?

Thanks

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/2 "2006-11-07T10:46:21Z")

</div>

Jim F. wrote:

> The problem is I have to add this to every test case since I can’t put  
> end
> 
> Has anyone ever needed such a thing? Is there a better way of solving  
> this problem?
> 
> Thanks

Untested - just sketching ideas:

mytest.rb:

require ‘test/unit’

class TC \< Test::Unit::TestCase  
def open\_data(f,&b)  
File.open(File.join(get\_dir, f), &b)  
end

def get\_dir  
x = caller(2).shift  
if /^(.\*):\d+:in / =~ x  
File.dirname $1  
else  
raise “Whatever”  
end  
end  
end

your\_test.rb:

class TestFoo \< TC  
def test\_x  
open\_data(“foo”) do |io|  
io.each\_line …  
end  
end  
end

```
robert
```

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/3 "2006-11-07T10:46:21Z")

</div>

I think this could get there:

```
def __REQUIRING_FILE__ ; caller[1] =~ /([^:]*):/; $1 end

```

But probably only if you don’t call it within any other methods. I’ll  
have to play around some more.

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/4 "2006-11-07T10:46:22Z")

</div>

Louis J Scoras wrote:

> I think this could get there:
> 
> def **REQUIRING\_FILE** ; caller[1] =~ /([^:]\*):/; $1 end
> 
> But probably only if you don’t call it within any other methods. I’ll  
> have to play around some more.

I played around already 🙂

def find\_dir  
caller.each do |cl|  
if %r{^(.\*):\d+(?::in )?$} =~ cl  
f = $1  
return File.dirname(f) if f != **FILE**  
end  
end  
raise “Not found”  
end

Regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/5 "2006-11-07T10:46:26Z")

</div>

On 10/30/06, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> end

Very nice.

I realized after I posted that ‘:’ could be a valid character in a  
filename, so my above try at it won’t work anyway.

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/6 "2006-11-07T10:46:33Z")

</div>

On 10/30/06, Jim F. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> module TestHelper  
> **REQUIRING\_FILE** = /([^:]\*):/.match(caller[1])[1]

Just make sure that you won’t have any file names with a ‘:’ in them =)

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/7 "2006-11-07T10:46:36Z")

</div>

Just make sure that you won’t have any file names with a ‘:’ in them =)

Sure:

**REQUIRING\_FILE** = caller.grep(/^(.\*):\d+(?::in)?$/)[0]

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:46am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/8 "2006-11-07T10:46:27Z")

</div>

Thanks guys.  
This is what I ended up with:

module TestHelper  
**REQUIRING\_FILE** = /([^:]\*):/.match(caller[1])[1]

TEST\_DIR = File.dirname( **REQUIRING\_FILE** )  
DATA\_DIR = File.join(TEST\_DIR, “data”)

def data\_file(file)  
File.join(DATA\_DIR, file)  
end  
end#module TestHelper

---

<div class="post-metadata">

**Author:** ![sauy7](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/ecc23a/32.png) [@sauy7](https://www.ruby-forum.com/u/sauy7)\
**Post date:** [November 7, 2006, 10:48am UTC](https://www.ruby-forum.com/t/file-for-requiring-file/74499/9 "2006-11-07T10:48:05Z")

</div>

On Tue, 31 Oct 2006, Jim F. wrote:

> Hello
> 
> I keep wondering if there is a way to have **FILE** be delayed in its  
> evaluation. For example, in my tests cases, I usually do the following so  
> that my test cases are imune to where they are run from:

you can defer the evaluation by simply using methods:

```
 harp:~/d > cat test/test.rb
 require 'test/unit'
 class TestMyClass < Test::Unit::TestCase
   require 'test/helper' and include TestHelper

   def __file__ () __FILE__ end
   def test_dir() File.dirname __file__ end

   def test_that_it_works()
     assert_nothing_raised{ p data_file('forty-two') }
   end
 end

 harp:~/d > cat test/helper.rb
 module TestHelper
   def data_dir() File.join test_dir, 'data' end
   def data_file(file) File.join data_dir, file end
 end

 harp:~/d > ruby test/test.rb
 Loaded suite test/test
 Started
 ."test/data/forty-two"
 .
 Finished in 0.00122 seconds.

 2 tests, 1 assertions, 0 failures, 0 errors

```

kind regards.

-a
