tags:

views:

122

answers:

1

I'm making a gem for internal use. In it, I load some YAML from another directory:

# in <project_root>/bin/magicwand
MagicWand::Configuration::Initializer.new(...)

# in <project_root>/lib/magicwand/configuration/initializer.rb
root_yaml = YAML.load_file(
  File.expand_path("../../../../data/#{RootFileName}", __FILE__))

# in <project_root>/data/root.yaml
---
apple:   100
banana:  200
coconut: 300

I'd rather not depend on the location of data/root.yaml relative to initializer.rb. Instead, I'd rather get a reference to <project_root> and depend on the relative path from there, which seems like a smarter move.

First, is that the best way to go about this? Second, if so, how do I do that? I checked out the various File methods, but I don't think there's anything like that. I'm using Ruby 1.9.

Right now, I create a special constant and depend on that instead:

# in lib/magicwand/magicwand.rb
module MagicWand
  # Project root directory.
  ROOT = File.expand_path("../..", __FILE__)
end

but I'm not sure I like that approach either.

A: 

If there's a main file you always run you can use that file as a reference point. The relative path (between the current directory and) of that file will be in $0, so to get the relative path to data/root.yaml (assuming that is the relative path between the main file and root.yaml) you do

path_to_root_yaml = File.dirname($0) + '/data/root.yaml'
Theo
@Theo: That's a good idea, but it would break during tests, when I often unit-test the classes directly rather than firing up the full application stack. My `$0` would be different in such cases (the path to the test runner, not my application).
John Feminella
Wrap the lookup in a simple object that you can stub out during testing.
Theo