Ruby Versioning And Gems
Contents of this page:
- Important
- Intro
- Useful resources
- Overview of versioning problems that can happen with Ruby projects
- What gems are / how gems work
- Staying up to date
- Different versions of Ruby
- Basic package management from RubyGems
- Bundler
- Errors / problems you might see
- Trouble getting Ruby working on a 2022 Macbook
- “Your XXX version is a.b.c, but your Gemfile specified d.e.f”
- Conflicting Ruby versions
- `warn_for_outdated_bundler_version’: You must use Bundler 2 or greater with this lockfile.
- “Could not find gem ‘YYY (~> a.b)’, which is required by gem ‘ZZZ (= c.d.e)’, in any of the sources.”
- “can’t find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)”
- Jekyll adds Windows-related dependencies to Gemfile
- “cannot load such file”
- Things you might do to fix a problem
- To do
Important
- Try to avoid versioning problems by keeping Ruby and all your gems up to date. See Staying up to date
Intro
Ruby is a great language in many ways, but the one thing that mars the experience of working with Ruby is the fact that you’ll often find yourself having to halt development work while you fix confusing Gemfile
errors such as “Your Ruby version is 2.6.3, but your Gemfile specified 2.6.5” or .”Could not find gem ‘bundler (~> 1.1)’, which is required by gem ‘middleman-core (= 3.3.7)’, in any of the sources.”
I can’t decide whether I should be proud or ashamed of the fact that for a long time, my reaction to these errors was to google them and then blindly follow the advice I found until things were working again. Proud, because I was focused and pragmatic - I had a goal in mind and didn’t want to be distracted by the rabbithole of researching exactly what was going on. Ashamed, because I was doing the equivalent of hitting it with a hammer until it worked - rather than getting a proper understanding and therefore the ability to find long term solutions and be confident that I wouldn’t find myself back in the same situation at some unpredictable point in the future.
If you look at my Jekyll troubleshooting page, you’ll see that I was simply recording error messages and solutions, with not much idea of what was actually going on or which actions were the ones that actually fixed my problems, and not much understanding of why things got fixed when they did.
So today I have put aside a whole day to dive in and get to grips once and for all with what the hell is going on with my Gemfile
.
Useful resources
- Bundler documentation
- Learn Tech guide on gem packaging (from Made Tech)
- Internal Made Tech workshop on Ruby versioning, bundling and managing gems (courtesy of George Schena)
- Brief bundler tutorial from Learn Enough Ruby on Rails (Learn Enough subscription might be needed, but at the time of writing (Jan 2021) this content was free).
- Article - Understanding ruby load, require, gems, bundler and rails autoloading from the bottom up
Overview of versioning problems that can happen with Ruby projects
There are two possible sources of version woes when working Ruby:
- Problems with versions of the gems (aka packages) your Ruby project is using.
- Problems with the version of Ruby your project is using.
These can sometimes be related - eg your project may depend on a particular gem that itself is dependent on a particular version of Ruby. Generally though, the two areas are handled by different means:
- You can simply have gems manually installed on your system, using
gem
commands. But most Ruby projects usebundler
to manage gem versions. This leads to the use of a file calledGemfile
, which will itself specify your Ruby version (in different ways depending on which Ruby version management system you’re using). - There are various different tools available to manage differing versions of Ruby between projects.
What gems are / how gems work
You can use the gem
command to use the RubyGems
software to find and install gems on your system. First you have to have RubyGems
installed, but Ruby 1.9 and newer ships with RubyGems
built-in. Every time you install a gem using gem install
, it will download the gem from rubygems.org and install it on your system. It will also download and install any dependencies that the original gem relies on, and so on for any dependencies of dependencies.
A gem is a Ruby software package. Each gem contains a packaged Ruby application or library. More concretely, it’s a zip file containing a bunch of ruby files and/or dynamic library files that can be imported by your code, along with some metadata.
You can install gems using the gem install
command, and there are lots of other useful gem
commands (eg gem list
to see what’s installed - more here) but this on its own does not allow you to control which gems are used by which projects. That’s where bundler comes in.
Staying up to date
- See also Different versions of Ruby
- NB: You should aim to always keep your Ruby version at the most stable version (in Jan 2021 this is 3.0.0).
- To find the latest stable version, go here.
- For advice on how to keep ALL your dependencies (ie gems as well as Ruby itself) up to date, see this article - which also gives advice on how to automate the process. GitHub’s dependabot will also help with this.
- …or follow this simple approach (there are some notes here re when I did this on 1/3/21 - see commits cd73da4 to d9548ea):
-
- Make sure all dependabot PRs are acted on (instructions here)
-
- Make sure dependabot security alerts are also acted upon (not the same as PRs) (they happen when PRs are not possible - see how dependabot works) (instructions here)
-
- Run bundle-audit weekly or monthly and act on all recommendations (instructions here)
-
- Make sure your main technologies are up to date (for this site, that’s Ruby and Jekyll)
-
- Run
bundle outdated
at regular intervals and then runbundle update [gem-name]
one at a time on each of the outdated gems, with a separate commit for each gem (fixing any related deprecation warnings in the same commit) (more detail here)
- Run
-
Acting on security recommendations with bundle audit
- Install bundle-audit (if not done already)
gem install bundle-audit
(or add toGemfile
)
- Run
bundle-audit
on command line - Act on recommendations ONE AT A TIME, with a separate commit for each one and testing as you go.
- eg if
rack
is listed as a vulnerability, runbundle update rack
- or if you are advised to remove a gem altogether:
- Search the code for all references (and remove them)
- Then remove the gem from
Gemfile
- See commits bcdd478 and ccac302 for an example
- eg if
Updating from dependabot branches
- See also How dependabot works
- Actions you can take:
- If dependabot branches are failing in Travis:
- Check / Google error messages in Travis
- Switch locally to the dependabot branch
- eg
git checkout dependabot/bundler/activesupport-5.2.4.4
- eg
- Make any changes designed to fix deployment errors
- eg see commit 15802e3
- this was when I’d fixed some deployment problems in the main branch but they weren’t in the dependabot branch, so I copied them to the dependabot branch for experimentation
- Push the branch to the remote, and check the build log in Travis to see if it’s fixed the problems
- IMPORTANT: Test locally. Does the site still work?
- If all is fine, merge the dependabot branch (in GitHub.com, visit Pull Requests at the top of the repo)
- If GitHub says there are merge conflicts:
- Merge the main branch into the dependabot branch locally (
git merge main
orgit merge master
) and fix conflicts there before merging
- Merge the main branch into the dependabot branch locally (
- If GitHub says there are merge conflicts:
- IMPORTANT: Test the deployed site too!
- DON’T FORGET: If you merged the PR at GitHub.com, you won’t have the updated main branch locally until you run
git pull
(orgit pull --rebase
)
- If dependabot branches are failing in Travis:
Acting on dependabot alerts
- See also How dependabot works
- Dependabot alerts live on the main front page in GitHub
-
or visit Security Dependabot alerts - They require a little more attention - see details in GitHub
- You may have to remove a gem altogether:
- Search the code for all references (and remove them)
- Then remove the gem from
Gemfile
- See commits bcdd478 and ccac302 for an example
How dependabot works
- See also Updating from dependabot branches
- Dependabot is a free service offered by GitHub - you can enable it there
- !! It does NOT necessarily catch all critical security updates. It’s worth using bundle-audit as well
gem install bundle-audit
(or add toGemfile
) then runbundle-audit
- although be aware that dependabot creates security alerts as a separate process to its main PRs - see below
- Dependabot identifies dependency updates and creates pull requests suggesting you update your dependencies.
- If you don’t merge the pull requests, they are not merged into your code base.
- The PRs create new branches and automatically trigger Travis deploys (or whatever CI integration you’re using). This is why you sometimes get failed builds that mention dependabot - it’s because Travis is trying to build the PR branch.
- It will actually trigger TWO Travis builds I think - one for what would happen if you built the dependabot branch as-is (“branch”), and one for if you built the branch merged into the main branch (“pull request”)
- If you click through to the PR in GitHub, you’ll see something like “all checks have passed”
- Then you can click “Show all checks” and you’ll see see two Travis builds - one for “branch” and one for “pull request”
- If you click Details on the right, it will take you through to Travis
- I think maybe every time you push new changes, the PR branch is automatically updated and Travis runs another build? Or it just keeps re-running them at regular intervals?
- Sometimes the PRs are closed automatically - for instance if you run a bundle update yourself and your dependencies are updated, so dependabot detects that the PR is no longer needed. Or because you make changes to your
Gemfile
so that the dependency that dependabot is trying to update is no longer even a dependency of your project.
- ALERTS:
- As well as PRs, there are also dependabot alerts
- These happen when PRs can’t be created - for instance because conflicting dependencies prevent an update to a non-vulnerable version
- These will live on the main front page in GitHub
-
or visit Security Dependabot alerts
Different versions of Ruby
Mac (OSX) and Linux
- The below notes are now probably out of date.
- This page is more up to date (Mar 2022)
- You can use asdf to manage Ruby versions - some details here
- The three main Ruby version management systems for Mac OSX and Linux (including WSL on Windows, but NOT vanilla Windows via GitBash) are:
- chruby
- This is what I’m currently using, via my Ubuntu system on Windows (NOT Ubuntu 16.04 (just because Ubuntu is the one I keep up to date and has everything in
~/.bashrc
)) - To list Ruby versions currently installed, just enter
chruby
at the command prompt. - To switch to a new version of Ruby do the following:
- If the new version not already installed:
- Cmd:
ruby-install ruby 2.6.5
- Restart your shell by typing
exit
and then restarting.
- Cmd:
- Then run cmd
chruby ruby-2.6.5
to switch to the new version. You can also put this command into your~/.bashrc
to effectively make that version your default, but remember to edit it when you upgrade Ruby!
- If the new version not already installed:
- More on chruby here and here
- This is what I’m currently using, via my Ubuntu system on Windows (NOT Ubuntu 16.04 (just because Ubuntu is the one I keep up to date and has everything in
- rvm
- rbenv
- Here is a brief discussion / comparison of all three.
- chruby
- No matter which system you use, the file
.ruby-version
can be used to specify your Ruby version. This is then referred to inGemfile
like this:ruby File.read(File.expand_path("../.ruby-version", __FILE__)).strip
Windows
If you’re coding Ruby in Windows, you’ll be using RubyInstaller. More here. But that doesn’t seem to allow you to switch between Ruby versions.
The solution is to either use WSL or WSL2 to run a Linux subsystem on your Windows machine, or use something like pik or URU, which are separate Ruby version managers for Windows.
Basic package management from RubyGems
- Even without
bundler
you get some package management - viarubygems.rb
.- The basic
gem
command is defined byRubyGems
- The basic
- Your
$LOAD_PATH
Ruby environment variable (only accessible to Ruby) holds the paths that Ruby searches when looking for gems (eg when executingload
andrequire
commands).- You can see all your Ruby environment variables by running
gem environment
on the command line. - NB When
rubygems.rb
is loaded, it replaces the defaultrequire
with a new version that also searches installed gems as well as searching$LOAD_PATH
- and updates$LOAD_PATH
on the fly to add the directory/ies specified by the installed gem.- Actually I’m not sure it does update
$LOAD_PATH
any more. When I tested this withirb
by runningputs $LOAD_PATH.grep(/json/)
and thenrequire('json')
and thenputs $LOAD_PATH.grep(/json/)
again, I didn’t get the effect described in this article. rubygems.rb
gets loaded when you runirb
. It also gets loaded when you run anyRuby
program, as long as you are using Ruby v1.9 or later. Otherwise you have to specifically add it into your app usingrequire 'rubygems'
- Actually I’m not sure it does update
- Be aware that if you’re building your own gem, there’s a lot of good practice to make sure you don’t cause problems with
$LOAD_PATH
More on this here. - Gems are installed by running the
gem install
command- You can see where they are installed by running
gem environment
and checking the setting forINSTALLATION DIRECTORY
. - Installing a gem means downloading its code from rubygems.org (if you have that configured as your gem source - you can check that via
gem environment
) and compiling any C code into dlls. - If you use
bundler
and have aGemfile
instead of usinggem install
, then when you runbundle install
it does the same asgem install
, and makes sure the specified version is installed. You could replicate this by manually runninggem install
for all the relevant gems and their versions (but probably wouldn’t want to).- Installing a specific version of a gem means that its directories are added to $LOAD_PATH and its activation is recorded. You can’t simultaneously activate two versions of the same gem.
- You can see where they are installed by running
- Questions:
- Is the change to
$LOAD_PATH
made byRubygems require
temporary or permanent?- See above. I suspect it’s not even true any more, but I’m pretty sure that when it was it was only temporary.
- If you can’t simultaneously activate two versions of the same gem, does this mean you can’t simultaneously have two Ruby programs running that use different versions of the same gem?
- I think the answer to that is yes - if you use a
bundle exec
command for each programme, then it just meansbundler
will load the correct version when starting the relevant piece of software. Once it’s running, the correct version is loaded into memory and everything continues happily?
- I think the answer to that is yes - if you use a
- Is the change to
- You can see all your Ruby environment variables by running
- When you use
require
to load a file, it will update the $LOADED_FEATURES Ruby environment variable.- It will also execute all the code in required gem - which might involve requiring other gems, and will mean that various methods (and maybe some global variables) get defined.
- The difference with
require
(as opposed toload
) is that it will not load the same code twice (it will returnfalse
instead).- Also, you can use
require_relative
to search in the same location as the file containing therequire
command (instead of searching$LOAD_PATH
).
- Also, you can use
- You can test this via
irb
with the following series of commands (create a filefoo.rb
in the current directory):
irb
require(`./foo.rb`)
puts $LOADED_FEATURES
- You might have to hunt through the long list of output, but
foo.rb
will be in there somewhere (quite likely at the end, in fact).
Bundler
NB: Try to avoid versioning problems by keeping Ruby and all your gems up to date. See Staying up to date.
- Run
bundle init
to create a brand newGemfile
. - bundler is itself a gem, which has to be installed like other gems (
gem install bundler
). bundler
is a gem package manager.- Interestingly
RubyGems
is also a package manager - the default one you’re using if you don’t have aGemfile
(and are therefore not usingbundler
), and you have Ruby v1.9 or higher… or you haverequire 'rubygems'
in your project. - Most people use
bundler
though (which itself usesrubygems
).
- Interestingly
- Once you have it installed, you can use
Gemfile
to specify your dependencies and (if you want) make broad (or specific) specifications about their versions.- Then when you run
bundle install
, bundler will install everything specified in your Gemfile AND all the dependencies of those gems, and their dependencies… all the way up the dependency tree. - Once it’s done, it creates
Gemfile.lock
which lists the exact version currently installed for every gem and every dependency. - You should check
Gemfile.lock
into source control so that you know exactly what versions of gems you are using for each commit. The exception to this is when you’re building a library - in which case you only commitGemfile
. The reason for this is that your library could end up being just one link in a dependency chain, and other versions may be required of upstream or downstream dependencies (I think).
- Then when you run
- In your Gemfile, this is the notation used to express version preferences:
~> 1.1
means version1.1
or later, but only if it’s prefixed1.1
. So1.1.5
would be installed, but1.2
would not.- Like this:
gem "redcarpet", "~> 3.4"
- Like this:
>= 1.1
would mean version1.1
or later, including1.2
,1.3
and even7.2
.- Like this:
gem "redcarpet", ">= 3.4"
- Like this:
1.1
specifies an exact version (not recommended)- Like this:
gem "redcarpet", "3.4"
- Like this:
- If you use
bundler
and have aGemfile
instead of usinggem install
, then when you runbundle install
it does the same asgem install
, and makes sure the specified version is installed. You could replicate this by manually runninggem install
for all the relevant gems and their versions (but probably wouldn’t want to). - Putting
bundle exec
before a command, e.g.bundle exec rspec
, ensures thatrequire
will load the version of a gem specified in yourGemfile.lock
as opposed to the most recent version. - If you’re using
bundler
, then you should add these two lines to the first file your application loads:
require 'rubygems'
require 'bundler/setup'
- (If you’re using Ruby 1.9 or later then you don’t actually need the first line)
- What
bundler/setup
does is alter your$LOAD_PATH
so that only the gems in yourGemfile
are put into$LOAD_PATH
.- This is useful because if you had installed a gem on your machine using
gem install
, and then required it in your code, but hadn’t added it to yourGemfile
, then anybody else downloading your code would get errors. This way you will also get the same errors, and that will remind you to add the gem to yourGemfile
. - More here and here.
- This is useful because if you had installed a gem on your machine using
- You can use
Bundler.require(:default)
as shorthand torequire
everything in yourGemfile
. - Bundler will not update dependencies of dependencies if it means the resulting gem will be a version incompatible with another gem that also depends on it.
- Question:
- Why didn’t
bundler/setup
work inserver.rb
when I removed omniauth but left the require statement in server.rb? - In commit ccac302 I made the relevant changes to server.rb, because in the previous commit I’d removed
omniauth
fromGemfile
, and everything went fine locally… but when I deployed tohroku
I got server errors saying there was arequire
statement forominauth
but no gem. - I assumed this was because I hadn’t done the
bundler/setup
thing, but when I experimented locally by addingbundler/setup
but leaving therequire
ijn place, everything still worked fine locally - when I would have expected to see the same error I saw inheroku
. - The original place I learnt about
bundler/setup
was here
- Why didn’t
Useful Bundler commands
- Update all gems:
bundle update
(exercise caution though)- The documentation on bundle update is quite good but you have to read it thoroughly and carefully!
bundle update
won’t update beyondGemfile
versions, and you can usemajor
andminor
to specify version details (see documentation), or you can change versions inGemfile
and runbundle install
. If you don’t runbundle update
and just runbundle install
a second time after having already run it once, you won’t get newer versions of gems even if they exist - it will just use whatever is inGemfile.lock
and won’t update anything.bundle update
with no qualifiers will update everything, but won’t go beyond the versions specified inGemfile
.
- Update multiple gems:
bundle update gem1 gem2 gem3
- This can be very useful if you’re trying to update one gem and keep getting errors about other related gems relying on different versions of each other - just update them all at once.
- Update one gem (and its dependencies):
bundle update gem-name
- To update it to a particular version, specify the version in
Gemfile
and then runbundle install
~> 1.2.1
means version1.2.1
or later, but only if it’s prefixed1.2
. So1.2.5
would be installed, but1.3
would not.- Like this:
gem "redcarpet", "~> 3.4"
- Like this:
>= 1.1
would mean version1.1
or later, including1.2
,1.3
and even7.2
.- Like this:
gem "redcarpet", ">= 3.4"
- Like this:
1.1
specifies an exact version (not recommended)- Like this:
gem "redcarpet", "3.4"
- Like this:
- To update it to a particular version, specify the version in
- Find out which gems are outdated:
bundle outdated
- Find out which gems have security vulnerabilities: Use bundle-audit:
gem install bundle-audit
(or add toGemfile
) then runbundle-audit
Errors / problems you might see
Trouble getting Ruby working on a 2022 Macbook
- (Seen by me when trying to get set up for the Made Tech Academy, Feb 2022)
- Getting Ruby working on a 2022 Macbook
- “I followed the step in this article in my laptop to check my rbconfig, and found that the system
ruby v.2.6.8
provided by Apple is indeed"host_cpu"=>"x86_64"
, while the ruby v.2.6.9 that I installed via rbenv is"host_cpu"=>"aarch64"
(=arm64). So perhaps some problem in apple’s default settings maybe…?”
“Your XXX version is a.b.c, but your Gemfile specified d.e.f”
(See also Conflicting Ruby versions below.)
- Example:
Your Ruby version is 2.6.3, but your Gemfile specified 2.6.5
- Explanation
- Your installed version of Ruby is 2.6.3, but your Gemfile has specified that this project requires a different version.
- This can happen on remote deployment platforms (eg Heroku) if you have pushed
Gemfile
but notGemfile.lock
(see below) - You might not find anything in your
Gemfile
which obviously specifies a Ruby version. Instead you might see something like this:ruby File.read(File.expand_path("../.ruby-version", __FILE__)).strip
- This indicates that you have a separate file called
.ruby-version
which tells you which version of Ruby your project is expecting - In my case my
Gemfile
and my.ruby-version
are both in the same folder, so I don’t know why the path (../
) specifies that the file is in the parent folder.
- Solutions:
- To find out which version of Ruby you have installed, type this at the command line:
ruby --version
- If this happens in Heroku, make sure you have checked in your
Gemfile.lock
as well as yourGemfile
- Install the correct version of Ruby:
ruby-install ruby 2.6.5
- Note then when I had this problem, this wasn’t enough - I also had to run
gem install bundler
and thenbundle install
- see questions below
- Note then when I had this problem, this wasn’t enough - I also had to run
- You might try using
chruby
, but when I did this it didn’t seem to work (see questions below):- Add stuff to
~/.bash_profile
and.ruby-version
as per https://github.com/postmodern/chruby - Cmd:
which ruby
- Cmd:
chruby_use /Users/clarey/.rubies/ruby-2.6.5/
- Add stuff to
- To find out which version of Ruby you have installed, type this at the command line:
- Questions:
- Why did I also have to run
gem install bundler
and thenbundle install
? - What’s all that
chruby
stuff? - Why does Heroku need
Gemfile.lock
as well asGemfile
?
- Why did I also have to run
Conflicting Ruby versions
- Example:
- I got various errors about Ruby versions when I first set this site up.
- Solutions:
- I originally fixed the project at Ruby version 2.6.5 by adding a
.ruby-version
file and referring to it inGemfile
. But then my system version of Ruby got updated to 2.7.2 (probably because of academny-related Ruby stuff) and things got screwy again. Currently I can’t runjekyll serve
because I get the error “Your Ruby version is 2.7.2, but your Gemfile specified 2.6.5”.
- I originally fixed the project at Ruby version 2.6.5 by adding a
- Questions
- How can I stop this problem from recurring every time I update Ruby?
- How can I keep Ruby up to date and avoid security weaknesses dur to not keeping Ruby and other dependencies up to date?
- Are the following all equivalent alternatives to
.ruby-version
?chruby
rvm
rbenv
- Experiments:
- Use
.ruby-version
to update the version of Ruby being used by this site. - Go back to Ruby version 2.6.5 system-wide. Check my other Ruby projects (academy stuff) aren’t broken by this.
- Find a way of having more than one version of Ruby installed - so that this project can be fixed at a different version.
- Once I have the Ruby version sorted, run
jekyll serve
to try and understand what all themingw
stuff is about. Or just use a previously-committedGemfile.lock
that contains themingw
stuff. - Update the Ruby version and then try to fix the formatting issue where the search box moves from right to left.
- Use
`warn_for_outdated_bundler_version’: You must use Bundler 2 or greater with this lockfile.
- Explanation:
- Presumably this comes from the “BUNDLED WITH” section at the bottom of
Gemfile.lock
(see questions below).
- Presumably this comes from the “BUNDLED WITH” section at the bottom of
- Solution:
gem install bundler
- Questions:
- Presumably you could also be more specific and run something like
gem install bundler -v 2.0
? - What’s the difference between having a version specified in
Gemfile
and having it specified inGemfile.lock
? The lock file tends to have a lot more version specifications thanGemfile
, and Heroku complains if it doesn’t have a lock file checked in. - There’s no reference to bundler in
Gemfile
, but it does say “BUNDLED WITH” and a version number at the bottom ofGemfile.lock
. Presumably this is where the error comes from?
- Presumably you could also be more specific and run something like
“Could not find gem ‘YYY (~> a.b)’, which is required by gem ‘ZZZ (= c.d.e)’, in any of the sources.”
- Example:
Could not find gem 'bundler (~> 1.1)', which is required by gem 'middleman-core (= 3.3.7)', in any of the sources.
- Explanation:
- It can’t find a particular version (
~> 1.1
) of a particular gem (bundler
), because another gem (middleman-core
, currently at version3.3.7)
) has specified that it is dependent on the missing gem. ~> 1.1
means version1.1
or later, but only if it’s prefixed1.1
. So1.1.5
would be installed, but1.2
would not.>= 1.1
would mean version1.1
or later, including1.2
,1.3
and even7.2
.
- It can’t find a particular version (
- Solution:
- Install the correct version of
bundler
and then reinstallmiddleman
:- Cmd:
gem install bundler -v 1.15
- Cmd:
bundle _1.15_ install
- Cmd:
gem install middleman
- Cmd:
- Install the correct version of
- Questions:
- Those actions above are just what I did before things started working again - doesn’t mean they were the correct or best solution. So…
- Did I really need to reinstall
middleman
? - What’s the difference between the first and second lines?
- Did I really need to reinstall
- Those actions above are just what I did before things started working again - doesn’t mean they were the correct or best solution. So…
“can’t find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)”
- Example:
- “/home/travis/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/rubygems.rb:308:in activate_bin_path’ /home/travis/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/rubygems.rb:289:infind_spec_for_exe’: can’t find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException)”
- Explanation:
- This happened to me when deploying on Travis. If you look closely, you’ll see it was in a Travis Ruby 2.5.1 directory. This seemed to come from the fact that I had
rvm
version2.5.1
specified in.travis.yml
.
- This happened to me when deploying on Travis. If you look closely, you’ll see it was in a Travis Ruby 2.5.1 directory. This seemed to come from the fact that I had
- Solution:
- I changed the
rvm
section of.travis.yml
to match.ruby-version
.- Something that confused me is that this section is not specifying the version of
rvm
, it’s specifying the version ofRuby
.
- Something that confused me is that this section is not specifying the version of
- I changed the
Jekyll adds Windows-related dependencies to Gemfile
- Example:
- Running
jekyll serve
on my Windows machine (for this website) results in Windows-related dependencies being added to yourGemfile.lock
(gems likeeventmachine (1.2.7-x64-mingw32)
are added, and a newx64-mingw32
entry is added in thePLATFORMS
section at the bottom), which then causes Heroku to complain that yourGemfile.lock
was created by Windows.
- Running
- Explanation:
- Maybe
jekyll serve
picks up on local platform settings and installs the relevant gems?
- Maybe
- Solutions:
- My main workaround is that I either manually remove all those
mingw32
entries or I just don’t check in the altered version ofGemfile.lock
. - Instead, could fix
Gemfile.lock
by running the bundle command in Ubuntu and then pushing the resultingGemfile.lock
up to the server?
- My main workaround is that I either manually remove all those
- Questions:
- What’s actually happening here? And is there a better solution?
“cannot load such file”
- You might need to run
bundle install
- If that doesn’t work, it might mean that you have not added the specified gem to your
Gemfile
. - For instance if you get “cannot load such file – rspec/core/rake_task”, then try adding
gem 'rspec'
to yourGemfile
.
- If that doesn’t work, it might mean that you have not added the specified gem to your
- If you get “command not found: bundle” then you might need to install Bundler:
sudo gem install bundler
- !! The password it wants is your laptop password
Things you might do to fix a problem
gem install bundler
- Example:
gem install bundler
- Note that this is typically folowed by
bundle install
- Explanation:
bundler
is a gem package manager
- Questions:
- Presumably
bundler
is itself a gem? - How does it know about versions of gems? Does it rely on
Gemfile
? - Will
Gemfile
work if you don’t havebundler
installed, or isGemfile
proprietary tobundler
? - Can you manage gems using other systems, or do you have to have
bundler
?
- Presumably
bundle install
- Example:
bundle install
- Explanation:
- This installs all the gems specified in your
Gemfile
- This installs all the gems specified in your
- Gotchas:
- Note that in Ubuntu 16 on Windows (using WSL), when I ran the
bundle
command to install rake, I had to add some permissions:sudo chown -R claresudbery:claresudbery /home/claresudbery/.bundle
- Note that in Ubuntu 16 on Windows (using WSL), when I ran the
- Questions:
- Locally or globally?
- Presumably you need
bundler
installed? - Can you have a functioning
Gemfile
without havingbundler
installed? - What does it mean to say that gems are installed?
bundle update
- Example:
bundle update
- Explanation:
- Sometimes when you run
bundle install
, you get a message saying you need to run bundle update first. In this case you should… runbundle update
first! - But be aware that
bundle update
will ignoreGemfile.lock
and update ALL dependencies, which can have unexpected results.- A less aggressive approach is to run
bundle update
on a specific package, like this:bundle update rack-cache
. Then only that package and its dependencies will be updated. - However,
bundler
will not update the dependency of an updated gem if it means the resulting dependency will be a version incompatible with another gem that also depends on it.
- A less aggressive approach is to run
- Sometimes when you run
- Questions:
- What does
bundle update
do? - Why does it sometimes need running before bundle install?
- What does
gem update
- Example:
gem update
- (Note that in Linux on Windows, I first had to run
sudo chown -R claresudbery /var/lib/gems/2.5.0/
to avoid permissions errors)
- Explanation:
- ???
- Questions:
- Is this the equivalent of
bundle install
if you don’t havebundler
installed? - I used this command on Linux in Windows. Is that relevant?
- Is this the equivalent of
gem install XXX
- Example:
gem install middleman
- Explanation:
- You’re installing the specific gem called
middleman
- You’re installing the specific gem called
- Questions:
- Presumably because you haven’t specified a version, you will get the latest release?
gem install XXX -v a.b
- Example:
gem install bundler -v 1.15
- Explanation:
- You’re installing a specific version (
1.15
) of a specific gem (bundler
)
- You’re installing a specific version (
gem install XXX YYY
- Example:
gem install bundler jekyll
- Explanation:
- You’re installing two gems at once (
bundler
andjekyll
)
- You’re installing two gems at once (
- Questions
- Am I right about this? I spotted it in my Jekyll installation instructions, but I’m guessing.
bundle a.b install
- Example:
bundle _1.15_ install
- Explanation:
- ???
- Questions:
- Is this something that only works on the version of bundler - because it’s using the
bundle
command to update itself - or if would this work on any gem, and in this case the gem in question isbundle
?- I suspect the former, because I don’t think there is a gem called
bundle
- the gem (if it even counts as a gem?) is calledbundler
. I could be wrong though.
- I suspect the former, because I don’t think there is a gem called
- Is this something that only works on the version of bundler - because it’s using the
bundle exec xxx
- Example:
bundle exec jekyll build
- Explanation:
- You’re prefixing command-line operations with
bundle exec
- You’re prefixing command-line operations with
- Questions:
- Is this so that everything you run will only use gems that have been installed using bundler?
- Does it mean you make sure you only use the gem versions specified locally for that project?
- Does it only work for command line operations?
- Does it only work when the things you are running on the command kine are themsleves gems?- If you get the error
Use chruby to manage your Ruby versions
-
See also Different versions of Ruby in this doc.
- Example:
- Add stuff to
~/.bash_profile
and.ruby-version
as per https://github.com/postmodern/chruby - Cmd:
which ruby
- Cmd:
chruby_use /Users/clarey/.rubies/ruby-2.6.5/
- Add stuff to
- Another example:
- Cmd:
brew install chruby
- Cmd:
source /usr/local/share/chruby/chruby.sh
- Cmd:
source /usr/local/share/chruby/auto.sh
- Cmd:
- Explanation:
- You’re using chruby to manage which version of Ruby is used by this project
- Questions:
- Does this mean that different projects can use different versions of Ruby?
- What’s the difference between the two examples above?
- What are the other tools that can be used to manage Ruby versions - eg
rvm
? - How come Travis appears to rely on
rvm
(hence the section in.travis.yml
used to specify your Ruby version) even though I’m not? Presumably this is because Travis is usingrvm
locally on its own servers?
Use ruby-install to specify a Ruby version
-
See also Different versions of Ruby in this doc.
- Example:
- Cmd:
brew install ruby-install
- Cmd:
ruby-install ruby 2.6.5
- Cmd:
- Explanation:
ruby-install
is what you use to install Ruby. In this case you’re specifying a particular version- Note that you might not have
brew
installed on your system.- If you’re in Windows, I think you have to use a dedicated installer.
- If you’re on a Mac or Linux, I think
yarn
is one of the alternatives tobrew
? - If you’re on Linux, the equivalent to
brew install
is often (always?)sudo apt-get install
- Fwiw personally I like using
brew
when I’m on a Mac - it allows me to have abrew
script which I can use to set up a new Mac with all my preferred software.
- Questions:
- If you don’t specify a version, will you get the latest stable release?
- Are there other Ruby installation tools available other than
ruby-install
? - Can you have old versions of Ruby hanging around on your system?
- I think there will be folders somewhere in your operating system that have particular versions in their names?
To do
- Answer the questions in this doc
- Update the academy gems presentation with any extra useful stuff I’ve learnt and documented here
- Update clare-wiki
- update Ruby version
- Update gems
- one at a time (see article below) - run
bundle outdated
and thenbundle update gem-name
on each of the outdated gems.
- one at a time (see article below) - run
- see this article - which also gives advice on how to automate the process.
- try getting bummr working?
- Fix problems with martin fowler
- I made a change to
class-too-large.xml
which I didn’t push to the remote repo because I wasn’t able to test it locally.- There’s a backup in Dropbox at Desktop\Current\refactoring
- If you run
work
and thenrs
you get the following error: “C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/bundler-1.17.3/lib/bundler/spec_set.rb:91:in `block in materialize’: Could not find ffi-1.11.2-x64-mingw32 in any of the sources (Bundler::GemNotFound)” - I’m pretty sure this is because it’s trying to use Ruby 2.7.0 (check out the folder in the path in the error message), and maybe the last time I ran it I was on Ruby 2.6.5?
- I tried running everything in Linux (Ubuntu - not 16.04) instead, because that way I could use
chruby
to switch Ruby versions - I got as far as installing the required version of Ruby, but then when I tried to run
bundle install
I got the error “/usr/lib/ruby/2.5.0/rubygems.rb:284:in `find_spec_for_exe’: Could not find ‘bundler’ (1.17.3) required by your /mnt/c/development/sudbery-mfcom/Gemfile.lock. (Gem::GemNotFoundException)” - When I tried to install the correct version of bundler using
gem install bundler -v 1.17.3
, I got the error “Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources” (I found this on stackoverflow, but didn’t have time to investigate further). - When I tried
bundle _1.17.3_ install
, I just got the same error as before (“Could not find ‘bundler’ (1.17.3)”) - I tried pulling latest changes from remote but that didn’t help either.
- I tried running everything in Linux (Ubuntu - not 16.04) instead, because that way I could use
- Once I get this working I need to test it locally before pushing it to the remote.
- I made a change to
- Answer unanswered questions in this doc
- Update to WSL 2 on my machine