如何在Ruby Gem中包含数据文件?

时间:2010-06-27 14:32:49

标签: rubygems

我正在开发一个Ruby gem,它使用可配置的“模板”来生成HTML。我想在gem中包含一组基本模板,并允许用户使用更好/更自定义的模板覆盖它们。这些模板不是Ruby代码,它们只是需要在代码中的某个时刻从磁盘读取的“文件”。

我查看了RubyGems文档,但是他们做出了(并非完全不合理)的假设,即gem只包含代码(好的,带有一些文档和特定的元数据文件)。没有提及如何创建等效的“/ usr / share / ...”文件。

在gem中包含此类文件的最佳做法是什么?我应该简单地将它们作为“来源”的一部分吗?如果是这样,我如何发现它们的路径,以便我可以将它们从磁盘读入模板处理器?

1 个答案:

答案 0 :(得分:10)

假设你有一个这样的项目结构:

bin/
|__ foobar*
lib/
|__ foobar/
|   |__ templates/
|   |   |__ a/
|   |   |__ b/
|___|__ meta.rb
|___|__ utils.rb

lib/foobar/teplates目录中,您有模板目录或 文件。

lib/foobar/meta.rb文件包含项目名称及其名称 版。保留它们(特别是版本号)很重要 与名称&同步宝石中项目的版本 规格。 (执行此操作的最佳方法是从Rakefile读取meta.rb 将值传递给规范。)

例如,meta.rb可能如下所示:

module Foobar
  module Meta
    NAME = 'foobar'
    VERSION = '0.1.2'
  end
end

然后编写一个函数,返回lib目录的完整路径 无论您是否从源头测试您的项目 目录或项目是从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

拥有Foobar::Utils.gem_libdir功能,您可以随时阅读 bin/foobar文件中的模板:

require_relative '../lib/foobar/utils'

puts Dir[Foobar::Utils.gem_libdir + '/*']
puts Foobar::Utils.gem_libdir + '/templates/a/blah-blah'