Reinstall Every Gem for Each Ruby Version

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.

How do I force Bundler to reinstall all of my gems?

bundle install --redownload

See the reference for bundle install: https://bundler.io/v2.2/man/bundle-install.1.html

or

bundle install --force

For older versions of bundler

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.

How to reinstall a gem using bundler

First I did a gem q --L, the shortcut for gem query --local. It outputs me the all the local gems installed.

actionmailer (3.2.8, 3.2.6, 3.2.1, 3.1.0)
actionpack (3.2.8, 3.2.6, 3.2.1, 3.1.0)
activemodel (3.2.8, 3.2.6, 3.2.1, 3.1.0)
activerecord (3.2.8, 3.2.6, 3.2.1, 3.1.0)
activeresource (3.2.8, 3.2.6, 3.2.1, 3.1.0)
activesupport (3.2.8, 3.2.6, 3.2.1, 3.1.0)
acts-as-taggable-on (2.3.3)
...

And then, following DVG advice, I uninstalled the gem using its correct name gem uninstall acts-as-taggable-on and ran bundle install. After that I was able to rails c or rails s again without any problem.

Manage gem dependencies based on Ruby version

Logic like you show will work fine for development dependencies since it will be evaluated at bundle install time.

It will not work for runtime dependencies since the logic will be evaluated at gem-build time and not when the gem runs in another environment.
RubyGems does not provide a way for you to specify different gems based on the runtime environment, so the only way you could support that would be to release two differently named versions of your gem with different gemspecs.

Personally, I don't see the point of putting development dependencies in the .gemspec, so I always just add these to my Gemfile and reserve the gemspec for runtime dependencies only.
This separates the concerns better and makes it clear that gem selection logic can be used in the Gemfile, but not in the gemspec.

How to remove all old Ruby versions (and version managers) and reinstall a single, tested version on macOS 10.14.6?

(Please make sure to see the Background section at the end of this answer.)

My procedure

1. Remove all the existing Ruby stuff (except for the Ruby "system" files installed by Apple for the "core system" for macOS).

This is the part of the procedure I'm less sure of. I've asked on superuser.com about "how to remove all possible, old Ruby cruft" and will import anything learned there to this procedure. In the meantime, I found a few things Ruby-related (eg: ~/.ruby-version) for which I could not easily find any documentation/reference. It was a mini adventure. But here's what I came up with:

a) Homebrew-based stuff: brew uninstall ruby ruby-build rbenv and any other Ruby-oriented Homebrew packages. brew list | grep can be helpful to find the packages.

b) rvm uninstall -- but please first read "old file droppings" notes below, in order to retain your old rvm environment for reference.

c) Any other uninstalls (non-Apple-macOS systems installs, of course) you can find or think of, possibly including installs that result from procedures found at https://rvm.io and https://github.com/rbenv/rbenv and any other version managers you can find/think of.

2. Remove or move old Ruby file droppings from $HOME

I moved the files instead of removing them, per the following procedure. Note that the ~/.rvm move effectively does some or all of the (1b) procedure above, while retaining the old ~/.rvm environment for (possibly very-helpful) reference, eg: to rebuild your installed-gems list. Also note that you may have more or less "file droppings" in your home directory.

 cd $HOME
mkdir -p .ruby-old-files/2020-04-13
mv .rbenv/ .rvm/ .gem/ .ruby-version .ruby-old-files/2020-04-13/

3. (Re)install the latest, "stable" (?) rbenv/"ruby engine" per this one-line command (this presumes Homebrew is already installed), given the rbenv version manager choice as described in the Background section below:

brew update
brew install rbenv

The above does not install the "Ruby engine" via Homebrew; rather, it install rbenv (via homebrew), which in turn installs the "Ruby engine" per the following:

rbenv install $(rbenv install -l | grep -v - | tail -1)
rbenv global $(rbenv install -l | grep -v - | tail -1)

4. Comment/delete previous ~/.bash_profile updates from past Ruby-isms

I ended up commenting out all these lines from past Ruby-driven updates, which appear to be unused by and/or conflicting with rbenv (your file may not have anything like this):

#export PATH=$PATH:~/.gem/ruby/1.8/bin:/usr/local/opt/ruby/bin
#export PATH="$PATH:$HOME/.rvm/bin" # Add RVM to PATH for scripting
#[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # Load RVM into a shell session *as a function*
# export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

5. Add this to ~/.bash_profile:

eval "$(rbenv init -)"

6. Start a new macOS Terminal.app window (or iTerm2 or similar).

7. [Optional] Re-install previous gems in new environment.

I looked at my previous .rvm bin list:

$ brew install tree
Warning: tree 1.8.0 is already installed and up-to-date
To reinstall 1.8.0, run `brew reinstall tree`
$ cd
$ tree -a .ruby-old-files/2020-04-13/.rvm/gems/ruby-2.2.1/bin/ -C | less
.ruby-old-files/2020-04-13/.rvm/gems/ruby-2.2.1/bin/
├── 3llo
├── _guard-core
├── asciidoctor
├── asciidoctor-safe
├── bundle
├── bundler
├── coderay
├── console
├── executable-hooks-uninstaller
├── github-markup
├── guard
├── imap-backup
├── listen
├── nokogiri
├── pry
├── rake
├── rdoc
├── ri
├── ruby_executable_hooks
├── setup
└── thor

0 directories, 21 files
$

(there's possibly other places to look for existing gems, as with Ruby stuff can be scattered all over the place with many "rubies" as the Ruby community calls them) and ran gem install [gem-package] for every package I wanted to reuse in my new (clean, fresh, and sane) Ruby environment. I ran some initial asciidoctor tests on my team's rather complex asciidoctor document library, and all seems initially good.

We'd prefer there be some sort of significant Ruby-engine set of "self diagnostics" (a simpler illustration: brew doctor) to give the user much more confidence that their "Ruby engine" is optimally functional. Alas, I as of yet see no such thing for Ruby.

From here moving forward I can gain more confidence in building multiple "rubies" via rbenv, and only rbenv. Before I had multiple rubies managed via multiple installers/version managers (Homebrew, rvm, and rbenv), which may have been a cause of many problems, possibly per Todd's point.

Background

Ruby has a bit of complexity and possibly runs much better with a version manager. I find this all a bit unusual, at least from my decades of swdev+sysadmin experience. I can certainly see how all these mechanisms can be very powerful. For now, I'm just trying to make my Ruby platform work.

From what I can tell, there is no "one standard way" to install and run and a standard directory to places in for Ruby on macOS. This means there's no "one standard way" to uninstall, and so one has to, if they've (often very unknowingly, like me) installed many different Ruby versions (I guess called "Rubies"?) over the years (decades?) in many different files/directories controlled by multiple different "version managers" (I guess? More on versions managers in a moment). ie, I find I have to "hunt and peck" for all the historical ways past Ruby installs/version_managers might have left file/directories placed in various areas.

Note this can happen when you have an macOS image that has lived for many years, and in my case, has been cloned across many generations of MacBooks. For someone who goes to a Ruby boot camp for a week and installs on a clean system, everything should work just peachy. For someone like me who's been an engineer/mgr for decades and possibly has all sorts of Ruby-isms laying around for his decades-old macOS image (as directed by many many different Ruby-based apps/guides on how I install stuff; not knowing that many of these procedures were effectively in conflict with each other), it can be quite the different story.

The Ruby platform apparently requires something called a Version Manager to run a Ruby platform (interpreter, compiler, engine, whatever it's called). I chose the rbenv (based upon this reference) version manager for the "install" portion of my procedure after removing/moving all the old stuff.

If it's not already obvious, it's (presumably?) best to avoid installing and running multiple version managers concurrently.

Installation options

There seems to be several ways to install the Ruby "core engine/platform" (my syntax, possibly only used by me) on macOS, with the 3-most-referenced options I've found noted below. (Note there are many other version managers to choose from not listed below.) I chose rbenv based upon this reference.

  1. via rbenv
  2. via rvm
  3. via Homebrew

(1.) and (2.) above are mechanisms that can install Ruby, and these mechanisms can be installed via Homebrew. But #1 and #2 will not install Ruby via Homebrew. This can be confusing.

It appears (1.) and (2.) also enable multiple versions of Ruby to run concurrently. (3.) may not. This may be helpful due to version-to-gem/app compatibility challenges with Ruby's aggressive (?) feature movement, which sometimes comes at the expense of backwards compatibility. (I'm guessing here, but can come up with no other good explanation; community, pls comment.)

The "remove all old Ruby engines and files" approach might be extreme. My experience: Ruby's history is a mess, and over the years/decades it left all sorts of messy variances (in my home directory) lying around. It's not a big deal for me to rebuild gems by hand -- there's not that many on my system. And by keeping the pre-existing Ruby-environment files around I'm (hopefully) covered if ever I need to revert or rebuild stuff. And, for now, things feel much more "clean and sane" now that it "feels" like I've removed all the old cruft.

Even more background

My team and I are only users of Ruby-based applications, not Ruby developers, and are far from experienced in the Ruby realm. We just want to install and use and maintain applications like Asciidoctor without having to "dive in deep" on all this Ruby stuff. Everything worked okay for several years - and then all the "cruft" built up and started breaking things. When I tore it all down and properly reinstalled (above)--once I finally figured out how all the Ruby ins and outs worked--things starting working again. I believe that I, as a simple Ruby-application user, should not have to go to this level of effort just to get a Ruby app to work. In short: it should not be this hard. Hence the nature of my comments about the difficulty.

Further, I had a bad day when I first posted this question and unnecessarily aggravated several community members here that were trying hard to help--and again, my apologies, that was totally my bad--and I have since been labeled by some as the guy that "likes to complain alot." And I thoroughly deserve that label being inappropriate in a couple of my comments. Again, I apologize.

Additionally: my Ruby problems still exist whether or not folks here want to deny it or simply blame the problems on me for being mean. Regardless: I'm not disappointed with the people trying to help; I'm disappointed with the Ruby platform not supporting my overall experience well.

Please also note TamerB's helpful answer.

Best way to update all of RVM rubies and gems after system update?

You can do:

rvm reinstall all

append --force to skip the questions.

Note that will do full reinstall including gem pristine of every gem, you need to pay attention to the output as it will notify you about the gems that failed to executes the pristine action.

Removing all installed Gems and starting over

From the RVM support site:

RVM installs everything into ~/.rvm.
To remove RVM from your system run 'rm
-rf ~/.rvm'. You may have one additional config file in ~/.rvmrc and
of course the RVM hook in your
bash/zsh startup files.

So, just go to the command line and type rm -rf ~/.rvm

All the installed gems are in the ~/.rvm folders, so doing the above will remove the gems and installed rubies in one go.

Gems you added pre-RVM with the default ruby install can be removed by typing this at the command prompt:

for x in `gem list --no-versions`; do gem uninstall $x -a -x -I; done

Don't reinstall if gem is already installed

You can use the --conservative flag with gem install.

gem install sqlite -v 1.3.8 --conservative

It won't install or update any gems that meet the version requirement.

Why does a Ruby version update require installing bundler?

Each copy of Ruby installed on a computer has its own set of installed gems. One reason that gems aren't shared between installations of Ruby is that some gems include compiled native code, and the compiled output might be different for different versions of Ruby.

bundler is a standalone gem, not part of Ruby, so whenever you install a new Ruby you have to install bundler in that Ruby.

This is independent of whether you're using a Ruby version manager (chruby, rbenv, rvm, etc.); if you install a new Ruby, it needs its own set of installed gems.



Related Topics



Leave a reply



Submit