Ruby require 'file' and relative location
Asked Answered
S

1

19

So I'm writing some rspec tests and I'm embarrassed at my lack of Ruby understanding.

I have a file structure that looks like the following:

  • GUI_Tests/Tests/test_spec.rb
  • GUI_Tests/windows_gui.rb
  • GUI_Tests/upload_tool.rb

when I run spec for the test_spec.rb file, I require the upload_tool file to be included like so:

spec -r ../upload_tool -fs test_spec.rb

Then, the upload_tool requires windows_gui.rb, like so:

require '../windows_gui'

My question is, why so I have to reference windows_gui.rb relative to test_spec.rb (requiring the ../) rather than the upload_tool.rb? This feels wrong to me, I'll want to use the upload_tool.rb out of context of the test specs, which means changing the requires each time.

Clearly I'm missing something, but if I don't reference relative to the test spec I get a file not found error.

Sorry for being so ignorant here, but I'm coming up empty handed. Any thoughts appreciated.

BB

Scriptural answered 15/7, 2010 at 17:35 Comment(2)
Don't feel bad - I find dealing with relative paths one of the most annoying things about ruby. I've listed it in what are the things you would like improved in the ruby languageCranach
August 2012 - Note that this post is now two years old. Most folks are now on 1.9.2. See this post https://mcmap.net/q/667651/-relative-file-path-in-rspec also for the best solution (Feb 2012)Isoprene
S
20

You don't. requires are relative to the current directory, which in your case was GUI_Tests/Tests. If you did this instead:

cd ..
spec -r upload_tool -fs Test/test_spec.rb

You would have to use this:

require 'windows_gui' # without '../'

The most common way to get around that problem is using File.dirname(__FILE__):

require File.join(File.dirname(__FILE__), '..', 'windows_gui')

NOTE: in Ruby 1.9.2 require changed it's defaults: Ruby: require vs require_relative - best practice to workaround running in both Ruby <1.9.2 and >=1.9.2

Staggard answered 15/7, 2010 at 17:47 Comment(3)
Perfect - like I said, I was embarrassed for even having to ask, but I'm glad I did. That makes perfect sense.Scriptural
Actually, require is not relative to the current directory, it is relative to the search path (i.e. the special constant $LOAD_PATH or its alias $: ). It just so happens that on older versions of Ruby (i.e. all except the not-yet-but-soon released 1.9.2), the current directory ( . ) is in the search path by default: p $:.include?('.') # => true . However, as of Ruby 1.9.2 that is no longer the case and shouldn't be relied upon. In Ruby 1.9, you could use require_relative which works relative to the source file it is called from instead of the search path.Noonday
@Jorg: But if I run this in 1.9: $:.replace []; require '../somefile', it works.Staggard

© 2022 - 2024 — McMap. All rights reserved.