Mikey Hogarth
Mikey Hogarth

Reputation: 4702

Using yaml files within gems

I'm just working on my first gem (pretty new to ruby as well), entire code so far is here;

https://github.com/mikeyhogarth/tablecloth

One thing I've tried to do is to create a yaml file which the gem can access as a lookup (under lib/tablecloth/yaml/qty.yaml). This all works great and the unit tests all pass, hwoever when I build and install the gem and try to run under irb (from my home folder) I am getting;

Errno::ENOENT: No such file or directory - lib/tablecloth/yaml/qty.yaml

The code is now looking for the file in ~/lib/tablecloth... rather than in the directory the gem is installed to. So my questions are;

1) How should i change line 27 of recipe.rb such that it is looking in the folder that the gem is installed to?

2) Am I in fact approaching this whole thing incorrectly (is it even appropriate to use static yaml files within gems in this way)?

Upvotes: 8

Views: 4749

Answers (1)

robustus
robustus

Reputation: 3706

Well first of all you should refer to the File in the following way:

file_path = File.join(File.dirname(__FILE__),"yaml/qty.yaml")
units_hash = YAML.load_file(filepath)

File.dirname(__FILE__) gives you the directory in which the current file (recipe.rb) lies. File.join connects filepaths in the right way. So you should use this to reference the yaml-file relative to the recipe.rb folder.

If using a YAML-file in this case is a good idea, is something which is widely discussed. I, myself think, this is an adequate way, especially in the beginning of developing with ruby.

A valid alternative to yaml-files would be a rb-File (Ruby Code), in which you declare constants which contain your data. Later on you can use them directly. This way only the ruby-interpreter has to work and you save computing time for other things. (no parser needed)

However in the normal scenario you should also take care that reading in a YAML file might fail. So you should be able to handle that:

file_path = File.join(File.dirname(__FILE__),"yaml/qty.yaml")
begin
  units_hash = YAML.load_file(filepath)
rescue Psych::SyntaxError
  $stderr.puts "Invalid yaml-file found, at #{file_path}"
  exit 1
rescue Errno::EACCES
  $stderr.puts "Couldn't access file due to permissions at #{file_path}"
  exit 1
rescue Errno::ENOENT
  $stderr.puts "Couldn't access non-existent file #{file_path}"
  exit 1
end

Or if you don't care about the details:

file_path = File.join(File.dirname(__FILE__),"yaml/qty.yaml")
units_hash =     
  begin
    YAML.load_file(filepath)
  rescue Psych::SyntaxError, Errno::EACCES, Errno::ENOENT
    {}
  end

Upvotes: 15

Related Questions