2010-06-27 5 views
9

Je travaille sur une gemme Ruby qui utilise des "templates" configurables pour générer du HTML. Je veux inclure un ensemble de modèles de base avec la gemme, et permettre aux utilisateurs de les remplacer par de meilleurs/plus personnalisés. Ces modèles ne sont pas du code Ruby, ils sont "juste des fichiers" qui doivent être lus à partir du disque à un moment donné dans le code.Comment inclure des fichiers de données dans un Ruby Gem?

J'ai regardé la documentation RubyGems mais ils font l'hypothèse (pas tout à fait déraisonnable) qu'une gemme contient seulement du code (OK, avec de la documentation et des méta-données spécifiques jetés pour faire bonne mesure). Il n'y a aucune référence à la façon de créer l'équivalent des fichiers "/ usr/share/...".

Quelle est la meilleure pratique pour inclure de tels fichiers dans la gemme? Devrais-je simplement les inclure dans les «sources»? Si oui, comment puis-je découvrir leur chemin afin que je puisse les lire à partir du disque dans le processeur de modèle?

Répondre

10

Supposons que vous ayez une structure de projet comme celui-ci:

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

Dans lib/foobar/teplates répertoire que vous avez vos répertoires de modèles ou fichiers. Le fichier contient le nom de votre projet et sa version . Il est important de les conserver (en particulier un numéro de version) synchronisé avec le nom & la version du projet dans votre gemme spécification. (La meilleure façon de le faire est lu meta.rb de Rakefile pour transmettre des valeurs à la spécification.)

Par exemple, meta.rb peut ressembler à:

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

écrire ensuite une fonction qui retourne un chemin complet le lib répertoire indépendamment du fait que vous testez votre projet à partir du répertoire sources ou le projet est installé à partir des 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 

Ayant Foobar::Utils.gem_libdir fonction, vous pouvez toujours lire vos modèles dans le fichier bin/foobar:

require_relative '../lib/foobar/utils' 

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