Reputation: 12214
I am using a gem that is only distributed in binary form. As such, we have two versions (not gem version numbers, just two different binaries) that we must somehow load conditionally in our environments since we develop on OS X and deploy on Linux (AWS).
I have these gems extracted to <app_root>/vendor/gems
like so:
chilkat-9.5.0.69-x86_64-darwin/
chilkat-9.5.0.69-x86_64-linux/
I realize that I can set a development
group and a production
group in Gemfile:
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
But that fails:
[!] 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.
What's more is that I can't get the Bundler to run correctly on the production
one by itself, maybe because it can't recognize the platform:
Could not find chilkat-9.5.0.69 in any of the sources
I don't know much about gemspec files, but maybe the last line:
--- !ruby/object:Gem::Specification
name: chilkat
version: !ruby/object:Gem::Version
version: 9.5.0.69
platform: x86_64-linux
tells Bundler to skip it if it specifies a different platform than the one on which it's running.
Initial Solution
by user ulferts below.
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
I had been trying to check Rails.env
but I wasn't aware of the RUBY_PLATFORM
constant.
However
Bundler appears to be deficient and lacks flexibility here. This fails upon attempting to deploy into production:
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.
So even though the conditional is there, it appears that the Gemfile.lock
file is causing there to be some kind of a problem. This is really unfortunate, because I don't think this legitimate use is that much of an edge case.
In short, even with a conditional, you can not have the same gem listed in your Gemfile twice. Whether for a different source, different version, or both.
I tried something else: changing the name of the gem in production. I changed the directory name, the gem name, and the references in the gemspec file. The result:
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
`vendor/gems/chilkat-9.5.0.69-x86_64-darwin``
So suddenly it looks like it doesn't even like the conditional now. I had a put a conditional in the code that did the require
to facilitate this, but I can't even get there if the code can't be deployed.
Upvotes: 1
Views: 1861
Reputation: 2242
The Gemfile
is just another ruby file. If you can figure out the architecture you are on, you can simply wrap it in an if ... else
e.g.
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
One possibility to differentiate would be setting an env variable in production.
Upvotes: 2
Reputation: 1659
Maybe you can use Install_if?
See http://bundler.io/man/gemfile.5.html#INSTALL_IF
Upvotes: 1