Haris Krajina
Haris Krajina

Reputation: 15276

Ruby \ Rubygems how do they decide which gems to load?

This is more curiosity question and not a problem. When many version are present on the system which ones are chosen when require command is used? Background of the story is: I was implementing bundler gem in project (not Rails project). I had no issues but other developers had issues, after quick investigation I realized that I did not use

require "bundler/setup"

which basically loads up bundled gems. Quick fix, but it got me wondering how does ruby via rubygems decide which gems to use. Since code broke because Ruby application used older version of one of the gems, and not the newer one. Meaning it does not use the "newest" gems, so what is logic behind it?

UPDATE

To further explain this question let say you have gems foo-1.0.1 and foo-1.0.2 when you say, require 'foo' how does ruby know which one to load?

Upvotes: 1

Views: 104

Answers (2)

matt
matt

Reputation: 79723

In Ruby you require a file rather than a gem. If that file isn’t found on the current load path, Rubygems will search the installed gems for a file with that name, and if it finds one the gem is activated (meaning that it gets added to the laod path) and the file is then required. Normally a gem will have a file with the same name in its lib dir. Only one version of a gem can be activated.

The gem that gets activated is the latest version available that is compatible with any other activated gems. Normally this will just mean that the latest version installed wil be activated, but this might not be the case if you have already activated some gems which declare dependencies on earlier version of the gem you’re trying to activate.

For example, if you have foo-1.0.1 and foo-1.0.2 installed, then require 'foo' (assuming they have a file named foo.rb in their lib dirs and no other gem does) will cause version 1.0.2 to be activated. However if you also have a gem bar which has a dependency on 1.0.1 then calling require 'foo' after bar has been activated will cause 1.0.1 of foo to be activated.

Futhermore, if you try to require them in the other order, require 'foo'; require 'bar'; then you will get something like

Gem::LoadError: Unable to activate bar-1, because foo-2 conflicts with foo (= 1)

Here you can’t activate bar, which depends on version 1.0.1 of foo because you have already activated version 1.0.2 of foo.

Upvotes: 3

maček
maček

Reputation: 77778

Without Bundler, you have to specify each gem you want. e.g.,

require 'my_gem'
require 'my_other_gem'

However, Bundler can make this a bit easier for you using a Gemfile

If this is your Gemfile

gem 'my_gem'
gem 'my_other_gem'

Calling this will include all gems

require 'bundler/setup'

Upvotes: 0

Related Questions