How to include data files in a Ruby Gem?
I'm working on a Ruby gem that uses configurable "templates" to generate HTML. I want to include a basic set of templates with the gem, and allow the users to override them with bette开发者_开发知识库r/more customized ones. These templates aren't Ruby code, they are "just files" that need to be read from the disk at some point in the code.
I looked over the RubyGems documentation but they make the (not altogether unreasonable) assumption that a gem contains only code (OK, with some documentation and specific meta-data files thrown in for good measure). There's no reference to how to create the equivalent of "/usr/share/..." files.
What is the best practice for including such files in the gem? Should I simply include them as part of the "sources"? If so, how do I discover their path so I can read them from the disk into the template processor?
Suppose you have a project structure like this:
bin/
|__ foobar*
lib/
|__ foobar/
| |__ templates/
| | |__ a/
| | |__ b/
|___|__ meta.rb
|___|__ utils.rb
In lib/foobar/teplates
directory you have your template directories or
files.
lib/foobar/meta.rb
file contains the name of your project and its
version. It's important to keep them (particularly a version number)
synced with the name & the version of the project in your gem
specification. (The best way to do this is read meta.rb
from Rakefile
to pass values to the spec.)
For example, meta.rb
may look like:
module Foobar
module Meta
NAME = 'foobar'
VERSION = '0.1.2'
end
end
Then write a function that return a full path to the lib
directory
regardless whether you are testing your project from the sources
directory or the project is installed from the rubygems.
utils.rb
:
require_relative 'meta'
module Foobar
module Utils
# Return a directory with the project libraries.
def self.gem_libdir
t = ["#{File.dirname(File.expand_path($0))}/../lib/#{Meta::NAME}",
"#{Gem.dir}/gems/#{Meta::NAME}-#{Meta::VERSION}/lib/#{Meta::NAME}"]
t.each {|i| return i if File.readable?(i) }
raise "both paths are invalid: #{t}"
end
# [...]
end
end
Having Foobar::Utils.gem_libdir
function you can always read your
templates in bin/foobar
file:
require_relative '../lib/foobar/utils'
puts Dir[Foobar::Utils.gem_libdir + '/*']
puts Foobar::Utils.gem_libdir + '/templates/a/blah-blah'
精彩评论