有没有办法让bundler自动要求gems而不在gemfile中指定它们?

时间:2015-05-07 18:22:32

标签: bundler

我正在尝试使用自定义的rspec格式化程序来处理使用bundler的多个项目。由于我已经将rspec格式化程序安装为全局gem,我希望我不需要将gem添加到每个项目的gemfile中。

有没有办法让捆绑器自动执行:

group :test { gem 'my-globally-installed-rspec-formatter' }

因此,测试环境中的任何项目都会自动加载该依赖项,但在实际的Gemfile中不需要它?

2 个答案:

答案 0 :(得分:0)

您可以将宝石放入.gemspec,但这与Gemfile

中的宝石基本相同

我如何解决问题的方法是在.gemspecGemfile中包含两行中间件,然后将Gemfile和{{1}中的所有gem依赖项移出}}

这是通过使用子模块来处理的。这对很多人来说都很可怕。

对于某些人而言,这可能就像飞行五个城市街区的太空船一样,但对于管理5个以上宝石的人来说,所有人都具有相同的依赖关系,这会有所帮助。除此之外还有通用的RuboCop标准,使用共享子模块也很有价值。

实施子模块后,.gemspec可能会显示为Gemfile当前版本的Celluloid,其中我们正在实施celluloid/culture子模块:

require File.expand_path("../culture/sync", __FILE__)
Celluloid::Sync::Gemfile[self]

引用此方法......

module Celluloid
  module Sync
    module Gemfile
      class << self
        def [](dsl)
          dsl.source("https://rubygems.org")
          dsl.gemspec
          Gems.gemfile(dsl)
        end
      end
    end
  end
end

Celluloid::Gems ...

中依次运行此方法
def gemfile(dsl)
  loader do |name, spec|
    params = [name, spec["version"] || ">= 0"]
    req = spec["gemfile"] || {}
    params << req.each_with_object({}) { |(k, v), o| o[k.to_sym] = v }
    current = dsl.dependencies.find { |d| d.name == name }
    dsl.dependencies.delete(current) if current
    dsl.gem(*params)
  end
end

private

def loader
  @dependencies.each do |name, spec|
    next if name == gem_name
    spec ||= {}
    yield name, spec
  end
end

通过预先加载到yaml ...

@dependencies文件进行循环
bundler:
nenv:
dotenv:

benchmark_suite:
  dependency: development

rubocop:
  dependency: development

pry:
  dependency: development

rake:
  dependency: development

rspec:
  dependency: development

coveralls:
  gemfile:
    require: false

celluloid:
  dependency: core
  version: ">= 0.17.0.pre7"
  gemfile:
    github: celluloid/celluloid
    branch: 0.17.0-prerelease
    submodules: true

celluloid-essentials:
  dependency: module
  gemfile:
    github: celluloid/celluloid-essentials
    branch: master
    submodules: true

celluloid-supervision:
  dependency: module
  gemfile:
    github: celluloid/celluloid-supervision
    branch: master
    submodules: true

celluloid-pool:
  dependency: module
  gemfile:
    github: celluloid/celluloid-pool
    branch: master
    submodules: true

celluloid-fsm:
  dependency: module
  gemfile:
    github: celluloid/celluloid-fsm
    branch: master
    submodules: true

celluloid-extras:
  dependency: module
  gemfile:
    github: celluloid/celluloid-extras
    branch: master
    submodules: true

timers:
  version: "~> 4.0.0"
  gemfile:
    github: celluloid/timers

rspec-logsplit:
  version: ">= 0.1.2"
  gemfile:
    github: "abstractive/rspec-logsplit"
    branch: "master"
    require: false

同样适用于.gemspec的技术如下:

require File.expand_path("../culture/sync", __FILE__)

Gem::Specification.new do |gem|
  #de Unique statements which are not shareable.    
  Celluloid::Sync::Gemspec[gem]
end

您应该自己查看celluloid/culture存储库以查看整个解决方案,其中包括一种在运行bundle update时自动更新各种gem中子模块的机制。

对于我们来说,上面解释和解决的问题非常烦人,它产生了这种方法,最终可能成为它自己的“产品”,特别是因为它也在Bundler中解决了other issues,但这整个安排很少真正需要。我想这种方法是有争议的。如果您对此策略感兴趣,我可以以可重用的方式发布我的解决方案。

答案 1 :(得分:0)

Actually I realized that there is an rspec flag --require which will autoload a dependency... So I was able to install the gem in my local rvm gemset, and then make a ~/.rspec file with:

if (folderalumno == "alumno2") {

and it automatically works in all my projects.