Bundler.require不需要gemspec中的依赖项

时间:2013-10-10 12:31:18

标签: ruby gem bundler

我有一个使用bundler的应用程序,目前工作正常,但我必须从项目的bin目录中运行它。现在我正在尝试将其转换为宝石。

bin/myexecutable(无变化):

#!/usr/bin/env ruby
require 'mygem'
MyGem::MyExecutable.new.main(ARGV)

lib/mygem.rb(无变化):

require 'rubygems'
require 'bundler/setup'
Bundler.require

require 'mygem/version'
require 'mygem/my_executable'

mygem.gemspec(新):

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'mygem/version'

Gem::Specification.new do |spec|
  # ... omitting boilerplate specs of gem ...

  spec.files         = `git ls-files`.split($/)
  spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
  spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
  spec.require_paths = ['lib']

  spec.add_development_dependency 'bundler', '~> 1.3'
  spec.add_development_dependency 'rake'

  spec.add_runtime_dependency 'bindata'
end

Gemfile(将依赖项移至mygem.gemspec):

source 'https://rubygems.org'
gemspec

当我安装gem并尝试运行可执行文件时,我得到:

.../resource_file.rb:2:in `<class:ResourceFile>': uninitialized constant ResourceFile::BinData (NameError)

将依赖项复制回Gemfile使其再次起作用,但现在我在两个位置有相同依赖项的冗余声明。

使用gemspec声明时为什么不起作用?

1 个答案:

答案 0 :(得分:3)

您需要在require 'bindata'的顶部拨打lib/mygem.rb

此外,我建议从mygem.rb

中删除这些行
require 'rubygems'
require 'bundler/setup'
Bundler.require

Bundler期望gems需要它们自己的依赖项(这样当你需要它们时它们仍然可以工作而没有Bundler)。当gemspec中有Gemfile时,Bundler.require直接需要您的宝石,但不需要任何依赖项。将它放入gem中将导致它与已经使用Bundler的应用程序交互不良,并创建从gem到Bundler的运行时依赖项(未在gemspec中声明)。

这是故意行为。关于这些Bundler问题有一些讨论: