Copying Gems from Previous Version of Ruby in Rbenv

Copying gems from previous version of Ruby in rbenv

I've been looking at this specifically from the perspective of upgrading and reinstalling without downloading. It's not trivial, and I recommend you do some cleanup of your gems to minimize the amount of processing/installation that needs to be done (e.g., I had five versions of ZenTest installed; I did 'gem cleanup ZenTest' before doing this). Be careful with 'gem cleanup', though, as it removes all but the LAST version: if you need to support an older version of Rails, manually clean up the versions you don't need.

I called this script 'migrate-gems.sh':

#! /bin/bash

if [ ${#} -ne 2 ]; then
echo >&2 Usage: $(basename ${0}) old-version new-version
exit 1
fi

home_path=$(cd ~; pwd -P)
old_version=${1}
new_version=${2}

rbenv shell ${old_version}

declare -a old_gem_paths old_gems
old_gem_paths=($(gem env gempath | sed -e 's/:/ /'))

rbenv shell ${new_version}

for ogp in "${old_gem_paths[@]}"; do
case "${ogp}" in
${home_path}/.gem/ruby*|*/.gem/ruby*)
# Skip ~/.gem/ruby.
continue
;;
esac

for old_gem in $(ls -1 ${ogp}/cache/*.gem); do
gem install --local --ignore-dependencies ${ogp}/cache/${old_gem}
done
done

There are three pieces that make this work:

  1. gem env gempath contains the paths (:-separated) where gems are installed. Because
    gems are shared in ~/.gem/ruby, I skip this one.
  2. gem install accepts --local, which forces no network connections.
  3. gem install accepts --ignore-dependencies, which disables dependency checking.

I had a fairly large list of gems to move over today and I didn't want to download from rubygems.org (plus, I needed older versions), so I whipped this up fairly quickly.

reinstall every gem for each ruby version?

Yes. Rbenv (and RVM) have separate "gem home" directories for each installed version of Ruby. There may be ways to symlink certain directories to get them to share, but this will likely lead to problems, particularly with gems that include native C extensions, which may or may not compile and run cleanly in multiple versions.

If you have a Gemfile, easiest thing is to just bundle install again for Ruby 2.0, giving you duplicate copies of many gems and Ruby-2.0 compiled versions of any native gems.

Installing gems to which Ruby with rbenv

The gem is installed into whatever your currently selected Ruby is. E.g.

rbenv shell 2.0.0-p247
gem install bundler # bundler is installed for Ruby 2.0.0-p247 only
rbenv shell 1.9.3-p447
gem install bundler # bundler is installed for Ruby 1.9.3-p447 only

Can I execute gems from outside an rbenv environment?

From the comments in your Github issue it seems you got the basic idea now; rbenv shims are nothing more than glorified shell scripts that tie a command to a particular currently active Ruby version.

But nothing prevents you from creating your own hard-coded shims. For example, let's say you want this global fpm command that is available outside any particular rbenv environment.

Here's a simple way to do it:

> rbenv local 2.4.1
> ln -s `rbenv which fpm` ~/.rbenv/bin/fpm24
> rbenv local --unset
> fpm24 --version
1.10.2

This will install a "shim" into ~/.rbenv/bin/fpm24 that is a hard-coded pointer to the 2.4.1 gem that rbenv has installed previously. Now this fpm24 command will work anywhere, as long as you have ~/.rbenv/bin in your PATH.

Updating ruby version with Rbenv but gems apparently not updated

Yes, you need to run bundle install for the active ruby version. Please make sure that the active ruby version, and the gemset for the application are set properly. Just do the following (in Linux/MacOS):

$ cat .ruby-version
ruby-1.9.3-p484

$ cat .ruby-gemset
your_app_name

And before gem update, please re-neter into the your application/gem folder.

$ cd ..
$ cd your_app_name

I have an additional note. If your application is a gem, there is no reason to add the .ruby-version, and .ruby-gemset files into the git repository, just add them into .gitignore file. When your application is a rails app, adding the files along with the Gemfile.lock into git repo has make sense, because you fix ruby version, and gem set for web-application to one that are those, which uniquely will work. Also some cloud services like heroku requires Gemfile.lock to be added into a git repo.



Related Topics



Leave a reply



Submit