10

I'm working on a Ruby application that is deployed as a gem. I'd like to include a read-only data file with the gem and am not sure how/where that should be packaged

For a little background, this application deals with the MIDI spec which includes hundreds of constant values. For instance, controller "Channel Volume" is always identified by the value 7. "Sustain" is identified by 64. etc etc... In the past, people have included these values as a large set of constants in their code. That's fine but it seems more appropriate to me to include those in a language agnostic format such as yaml

Using the GEM_PATH to locate the yaml file is ugly and also wouldn't work when using the library in a non-gem deployment.

Thank you for your help

Nik Reiman
  • 39,067
  • 29
  • 104
  • 160
Ari Russo
  • 273
  • 2
  • 10

4 Answers4

11

I don't think RubyGems makes any assertions about where you should store files like this. I would put it under lib/ and do like @mkrmr says. I would use File.expand_path, though, because it's less typing and fixes some occasional problems with symlinks and moving files: YAML.load_file(File.expand_path('../../midi_codes.yml', __FILE__))

Ian
  • 2,078
  • 1
  • 17
  • 27
  • Thank you. I'll read up on expand_path, but that sounds like a good tip. Just out of curiosity, why lib/ ? – Ari Russo May 25 '11 at 23:47
  • 1
    If it were a config file, or the user was supposed to update it, I might put it in the root. I look at the Gem directory structure as an interface that exposes tests, documentation, installation, and gem code through directories. IMHO, this data file most closely falls into the category of "gem code", and should therefore go in lib/. It says to others "don't touch this unless you're coding on this gem." It's also what I've seen other gems do. – Ian May 25 '11 at 23:56
7

There is a specified location for these files.

  1. Create a folder called <gemdir>/data in your gem
  2. Use the Gem.datadir method to locate this directory.

This appears to create a directory that is expected to be public.

If you want this file to be private,then using the File.dirname(__FILE__) + "/path" trick will accomplish that.

Michael Bishop
  • 4,240
  • 3
  • 37
  • 41
  • Can you support your answer with a link to some documentation or other trusted source which says that the `datadir` directory's purpose is indeed to store the *static and predefined* data, not some user data or something, please? – skalee Mar 28 '17 at 01:34
  • I saw it in the source code: https://github.com/rubygems/rubygems/blob/master/lib/rubygems.rb#L360 It does appear to be deprecated. – Michael Bishop Mar 28 '17 at 13:06
7

If you place this file somewhere within the source tree of your Gem you can use a relative path to load it. From where you want to read it you can define the path like so: File.dirname(__FILE__) + "/here/is/my/file.txt"

You can use the path modifier .. like you would on the shell to go up a directory.

Mark
  • 1,058
  • 10
  • 13
1

The Rubygems package manager has its static files placed inside lib directory. For example, certificates (*.pem) are stored in lib/rubygems/ssl_certs. I believe they can be considered as the most authoritative source, thus I recommend you to do the same.

skalee
  • 12,331
  • 6
  • 55
  • 57