如何在Rails 4.2 Gemfile中有条件地加载本地gem?

时间:2017-10-05 14:20:02

标签: ruby rubygems bundler

我正在使用仅以二进制形式分发的gem。因此,我们有两个版本(不是宝石版本号,只是两个不同的二进制文件),我们必须以某种方式在我们的环境中有条件地加载,因为我们在OS X上开发并在Linux(AWS)上部署。

我将这些宝石提取到<app_root>/vendor/gems,如下所示:

chilkat-9.5.0.69-x86_64-darwin/
chilkat-9.5.0.69-x86_64-linux/

我意识到我可以在Gemfile中设置development组和production组:

group :development do
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-darwin'
end

group :production do
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-linux'
end

但那失败了:

[!] There was an error parsing `Gemfile`: You cannot specify the same gem twice coming from different sources.
You specified that chilkat (>= 0) should come from source at `vendor/gems/chilkat-9.5.0.69-x86_64-darwin` and source at `vendor/gems/chilkat-9.5.0.69-x86_64-linux`
. Bundler cannot continue.

更重要的是,我无法让Bundler在production上独立运行,可能是因为它无法识别平台:

Could not find chilkat-9.5.0.69 in any of the sources

我对gemspec文件了解不多,但可能是最后一行:

--- !ruby/object:Gem::Specification
name: chilkat
version: !ruby/object:Gem::Version
  version: 9.5.0.69
platform: x86_64-linux

告诉Bundler如果它指定的平台与运行它的平台不同,则跳过它。

初始解决方案

由下面的用户ulferts。

if RUBY_PLATFORM =~ /darwin/
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-darwin'
elsif RUBY_PLATFORM =~ /x86_64-linux/
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-linux'
end

我一直试图检查Rails.env,但我不知道RUBY_PLATFORM常数。

然而

Bundler似乎有缺陷,缺乏灵活性。尝试部署到生产中时失败:

You are trying to install in deployment mode after changing
your Gemfile. Run `bundle install` elsewhere and add the
updated Gemfile.lock to version control.

因此即使条件存在,Gemfile.lock文件似乎也会导致出现某种问题。这真的很不幸,因为我认为这种合法用法不是一个边缘案例。

简而言之,即使使用条件,也不能在Gemfile中列出两次相同的gem。是否为不同的来源,不同的版本,或两者兼而有之。

我尝试了其他的东西:在生产中更改宝石的名称。我更改了gemspec文件中的目录名称,gem名称和引用。结果:

You have added to the Gemfile:
* source: source at `vendor/gems/chilkatprod-9.5.0.69-x86_64-linux`
* chilkatprod

You have deleted from the Gemfile:
* source: source at `vendor/gems/chilkat-9.5.0.69-x86_64-darwin`
* chilkat

You have changed in the Gemfile:
* chilkat from `no specified source` to `source at

`供应商/宝石/奇尔卡特-9.5.0.69-x86_64的-darwin``

突然看起来它现在甚至不喜欢条件。我在执行require的代码中设置了一个条件来促进这一点,但如果代码无法部署,我甚至无法实现。

2 个答案:

答案 0 :(得分:2)

Gemfile只是另一个ruby文件。如果你能弄清楚你所在的架构,你可以简单地将它包装在if ... else例如

if architecture_is_os_x?
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-darwin'
else
  gem 'chilkat', path: 'vendor/gems/chilkat-9.5.0.69-x86_64-linux'
end

区分的一种可能性是在生产中设置env变量。

答案 1 :(得分:0)

也许您可以使用 Install_if

请参阅http://bundler.io/man/gemfile.5.html#INSTALL_IF