Ruby Bundler Multiple Sources in Gemfile

How can I avoid bundlers warning about multiple sources when I have all gems in my .gemspec?

No, you'll either need to mute the warning or add the source block to your Gemfile with the specific gems you want to come from your private server. There isn't a need to duplicate the ones that come from rubygems.org (or you could do it the other way around, if you depend on more private gems than public ones, and your private gems do not themselves depend on public ones).

The problem is that the gemspec format has no support for specifying the source for each gem, so without duplicating them into the Gemfile, there is no way to specify which gems come from each source.

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.

Bundler - Resolving Dependencies from different sources

It looks like the docs say no (very bottom):

SOURCE PRIORITY

When attempting to locate a gem to satisfy a gem
requirement, bundler uses the following priority order:

  1. The source explicitly attached to the gem (using :source, :path, or
    :git)
  2. For implicit gems (dependencies of explicit gems), any source,
    git, or path repository declared on the parent. This results in
    bundler prioritizing the ActiveSupport gem from the Rails git
    repository over ones from rubygems.org
  3. The sources specified via
    global source lines, searching each source in your Gemfile from last
    added to first added.

The relevant one being #2 here. It's a little vague but I think this other part of the docs helps clarify:

Bundler will search for child dependencies of this gem by first looking in the source selected for the parent, but if they are not found there, it will fall back on global sources using the ordering described in SOURCE PRIORITY.

So it sounds like you need to provide rubygems.org as the fallback global source if you want that to be the case, i.e. using the source 'http://rubygems.org' line on its own as you have done in your answer. Otherwise when looking for child gems (dependencies) it will look only on the source provided for the parent.

That said, I also have a company Gem-in-a-box server and tried to reproduce your issue but could not, so I'm not positive I'm interpreting those docs correctly.

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/

Rails: How to speficy different sources for gemfile when in development/production

Your gem file is correct but you need to change the way you execute the bundler since it doesn't know about Rails and the current environment.

To install in the production environment:

  bundle install --without development

To install in the development environment:

  bundle install --without production


Related Topics



Leave a reply



Submit