Bundler - Load Multiple Gemfiles

Bundler - load multiple Gemfiles

A Gemfile is "just Ruby". You can search for any other Gemfiles needed and include them, if you want to...

Update: see http://madebynathan.com/2010/10/19/how-to-use-bundler-with-plugins-extensions/

How can I use multiple Gemfiles for my application?

I agree that using two Gemfiles is bad practice, and have found a solution that involves the RUBY_PLATFORM constant along with the platform flag in my Gemfile. This may not be the MOST elegant solution, but it does work for me.

Here is a chunk of my code for curious readers:

group :development, :test do
# Mac OSX notifications
gem 'growl_notify' if RUBY_PLATFORM.downcase.include?("darwin")
gem 'growl' if RUBY_PLATFORM.downcase.include?("darwin")

# Gnome notifications => aka for Linux
gem 'libnotify' if RUBY_PLATFORM.downcase.include?("linux")

# Guard-spork doesn't work with windows but it's
# awesome for other Operating Systems.
gem 'guard-spork' if RUBY_PLATFORM.downcase.include?('darwin') || RUBY_PLATFORM.downcase.include?('linux')

# Windows Rubies (RubyInstaller)
platforms :mswin, :mingw do
# Windows notifications
gem 'rb-notifu'
end
end

How to combine gems from multiple Gemfiles to run one Ruby program?

The answer is that the top-level Gemfile should include the child directory Gemfiles.

Something like this (from Redmine 2.0 Gemfile)

# Load plugins' Gemfiles
Dir.glob File.expand_path("../plugins/*/Gemfile", __FILE__) do |file|
puts "Loading #{file} ..." if $DEBUG # `ruby -d` or `bundle -v`
instance_eval File.read(file)
end

Ruby Bundler - Multiple Ruby versions in the same gemfile

Gemfiles Declare Dependencies

A Gemfile declares a dependency on a Ruby version, with or without semantic versioning constraints. It is not meant to control multiple build targets for your application. It simply enforces that the Ruby version available to your app/gem is whatever you've defined. For example:

# Will fail if run with a different RUBY_VERSION.
ruby '2.2.4'

# Allows RUBY_VERSION >= 2.2.4, but <= 2.3.
ruby '~> 2.2.4'

# Allows either Ruby 2.2.4+ or 2.5.5+, with
# a minimum (but no maximum) patch version.
ruby '~> 2.2.4', '~> 2.5.5'

However, it won't install a given Ruby, nor do anything other than raise an error and a non-zero exit status when running bundler install. You need to take a different approach to test multiple targets.

Changing Build Targets with Continuous Integration (CI) Tools

If you're using an external CI like TravisCI, you can create a build matrix that targets multiple Ruby versions to test against. Whether you remove the Ruby version constraint altogether, or specify a supported range, is up to you. Leveraging your CI tool to build against the versions of Ruby you plan to support is really the best approach, though, whether or not you constrain your Ruby runtime in a Gemfile.

For example, you might use a matrix in your travis.yml like so:

language: ruby
rvm:
- 2.2.4
- 2.5.5

Switching Gemfiles

If you insist on doing it the way you're doing it, with a singular Ruby version allowed in your Gemfile, then you might consider having two separate gemfiles with different names in your source tree, such as Gemfile-2.2.4 and Gemfile-2.5.5. You can then specify which Gemfile to use with Bundler's --gemfile flag , or by symlinking a custom Gemfile to the canonical Gemfile for your project.

Here are some examples to consider:

# Resolve against a specific Gemfile with
# hard-coded Ruby version.

$ ls Gemfile*
Gemfile-2.2.4 Gemfile-2.5.5

$ bundle install --gemfile="Gemfile-2.2.4"
# Resolve against whatever custom file is
# symlinked to your ./Gemfile.

$ ln -sf Gemfile{-2.5.5,}

$ ls -F Gemfile*
Gemfile@ Gemfile-2.2.4 Gemfile-2.5.5

$ bundle install

Both approaches work, but the former is more flexible at the cost of needing to specify your chosen Gemfile each time, while the latter can help when you have a development/testing workflow that doesn't support Bundler's --gemfile flag.

Changing Rubies with Ruby Managers

If you have multiple Ruby versions in development, best practice is to use a version manager such as rvm, rbenv, or chruby. You can use your version manager to change rubies back and forth manually as needed.

You might also check whether your version manager supports auto-switching on .ruby-version or other configuration files. You'd still have to update that file each time you want to build or test against a different Ruby, but you wouldn't have to keep changing your Gemfile contents, re-pointing the Gemfile symlink, or updating a flag on each call to Bundler.

Whether or not any given approach is better than others will depend on your workflow. No technical solution will fit all circumstances, so your mileage may legitimately vary.

Composing one Gemfile from multiple others

You can also use eval_gemfile:

gemfiles = [ 'Gemfile.global' ]
gemfiles.each do |gemfile|
eval_gemfile gemfile
end

using bundler to load different versions of gems for different platforms

You can do it like that:

# Windows
gem "eventmachine", "~> 1.0.0.beta.4.1", :platform => [:mswin, :mingw]

# C Ruby (MRI) or Rubinius, but NOT Windows
gem "eventmachine", :platform => :ruby

Full list of available platforms:

ruby      C Ruby (MRI) or Rubinius, but NOT Windows
ruby_18 ruby AND version 1.8
ruby_19 ruby AND version 1.9
ruby_20 ruby AND version 2.0
mri Same as ruby, but not Rubinius
mri_18 mri AND version 1.8
mri_19 mri AND version 1.9
mri_20 mri AND version 2.0
rbx Same as ruby, but only Rubinius (not MRI)
jruby JRuby
mswin Windows
mingw Windows 'mingw32' platform (aka RubyInstaller)
mingw_18 mingw AND version 1.8
mingw_19 mingw AND version 1.9
mingw_20 mingw AND version 2.0

You can find more information in Gemfile(5) man page here (see 'Platforms' section).

Another approach is to use RUBY_PLATFORM constant:

if RUBY_PLATFORM =~ /win32/
gem "eventmachine", "~> 1.0.0.beta.4.1"
else
gem "eventmachine"
end

I haven't seen full list of available values for RUBY_PLATFORM but you can run

ruby -e 'puts RUBY_PLATFORM'

on both your platforms and see the difference.

Getting rails console to work with multiple Gemfiles

The trick was to fully disable Spring, rather than just restart it:

DISABLE_SPRING=1 BUNDLE_GEMFILE=Gemfile_5 bundle exec rails console
Loading development environment (Rails 5.0.7.1)


Related Topics



Leave a reply



Submit