Cleaning gems from older gem version - ruby

I recently upgraded my distro (Ubuntu from 16.04 to 18.04), and I guess either on the upgrade or on the regular sudo update/upgrade calls gem was upgraded and I currently have the 2.7.6 version. I barely use Ruby lately, but just now I had to run a jekyll/bundle command which returned me that it had a bad interpreter (it was looking for ruby2.3 and it's currently installed on the 2.5 version).
My next step would be updating the jekyll and bundle gems (so they update the interpreter version), but to my surprise they aren't listed when I run gem list. They were obviously installed since there's a /usr/local/bin/jekyll executable and a /usr/local/bin/bundle one as well. But I think when gem was upgraded it started checking gems on a different folder (/var/lib/gems/2.5.0 I'm guessing) but jekyll/bundle apparently are in /var/lib/gems/2.3.0. I'd be fine just installing jekyll/bundle on the 2.5.0 version, but is there a way to remove all gem files from the older version since they are useless now?

I highly recommend you to use a ruby version manager like rvm or rbenv to manage different ruby versions installed on your system.
If you just want to remove the gems from your disk, you can find the location of each gem with the command bundle show $gem_name and delete the parent directory to delete all of them. You may need to delete the Gemfile.lock as well to reset the locked gem versions.

Here's what I recommend:
Use rbenv for multiple Ruby version management, no customizations needed
a ruby installer plugin is now included with rbenv
it also handles ruby executable shims automatically, don't need to rbenv rehash anymore
it loads really fast (rvm has a noticable load time on shell startup)
Use bundler to dynamically resolve gems at runtime (options below)
it's fast enough anyways
don't need a special gem solution, bundler comes included /w Ruby now
Options to invoke bundler dynamically (I recommend the last one):
use bundle exec in front of every ruby executable
variant: create alias be='bundle exec'
create bundle binstubs <LIST GEM EXECUTABLES YOU WANT> for each project
use bin/ in front of every ruby executable to call the binstubs
do #2 and then set up .git/safe
lets you manually allow PATH lookups to the bin/ folder while in that project root
don't need to type bin/ anymore
Now multiple gem versions will all be installed into the same Ruby version bucket, and you let bundler dynamically add the right versions to the load path before every startup.
Removing a Ruby version will also mean removing all the gems (and versions of those gems) installed for that Ruby version as well.

I'd like to thank both answers. I upvoted them because even though they're not a direct solution to my problem they give good directions to prevent it.
NOTE: These are the steps I took, which doesn't mean they are the correct way, so don't take more as a reference than a guide.
Here's what I did to clean up those old Ruby version gems:
First I needed to add an environment variable for gem to be able to find those obsolete gems, by running GEM_PATH=/var/lib/gems/2.3.0.
Then it's possible to get the contents and specification of the gems with gem contents name_of_gem and gem specification name_of_gem.
I individually uninstalled those gems that were obsolete with sudo GEM_PATH=/var/lib/gems/2.3.0 gem uninstall -i /var/lib/gems/2.3.0 name_of_gem. In my case I did a sudo install, so I needed sudo which also required me to set the environment variable again because of sudo's security policy. Also, I needed to manually set the install directory for some reason.
Some gems will have executables, and the uninstall will ask if you want to remove it. I wasn't able to get the gem uninstall to remove it because it claimed I didn't have write permission to /var/lib/gems/2.3.0/bin (which is weird because the EXECUTABLE DIRECTORY gem environment variable was /usr/local/bin). I asked gem not to remove the executables, wrote down their names and removed them manually from the EXECUTABLE DIRECTORY folder. You can also use which gem_executable_name to find out where it's located.
After uninstalling all the gems I believe it's safe to remove the /var/lib/gems/2.3.0 folder and its contents. Running gem contents on all of them only returned me files on this folder so I believe the only external files were the script/executables that were added to /usr/local/bin.

Related

Can Ruby's Sass gem be manually installed?

I work inside a corporate firewall. I am using Windows 10 and have the Ruby 2.4 x64 install.
I need to get the sass gem. I cannot do it through the command line because all external calls such as this are blocked and will not be unblocked for my situation. Is there a place I can manually download the sass gem, and then issue the command to install the gem from a local file?
I'm in the same position and use two techniques
through the firewall
See my answer at installing-gems-from-behind-a-corporate-firewall
from a local file
You download the gem from https://rubygems.org/downloads/sass-3.5.4.gem
You can put the file in your ruby\bin folder and delete it later.
Then you cd to your bin folder and install it in the console with the command
gem install sass-3.5.4.gem --local
the 3.5.4 is the current version.
If there are dependencies (other gems) you need to first download them as wel.
Can't see what these are because on this machine I'm still using Ruby MRI 1.9.3 and the current version of sass requires Ruby 2.0.0
See also my answer here
deploy-a-ruby-gem-local-without-using-git-or-internet-access

How to install a gem so that it executes independent of currently active RVM gemset?

I am writing a dev command-line tool gem (let's say called "tool") which I would like to use in any place in the system. I use RVM for different projects, but this tool should be available from the command-line inside those projects.
If I simply install the gem globally using "gem install" (let's say it installs to /usr/local/bin/tool), the executable is of course available inside of other projects, but since the gemset changed when executing "tool" it fails saying that it cannot find the "tool" gem (because "tool" was never installed to that gemset). I don't want to add the gem to all the Gemfiles of all the projects.
What's the best way of dealing with this? Perhaps there is a way to "lock" the gem_path/gem_home in the executable at the time of installation?
It turned out that https://github.com/sportngin/brew-gem does what I want, installing a Rubygems gem via brew and locking its GEM_HOME and GEM_PATH in a bin wrapper it generates, so that everything works even when executed in the context of a different RVM gemset.
I forked it into https://github.com/gtmax/brew-gem, adding support for installing a brew gem from a local.gem file or from a gem project on github.

I'm using rbenv, so why are there two Gem paths on my system? (OS X Lion)

To clarify, I'm using rbenv to manage my ruby versions. I was under the impression that binaries are managed as shims in their respective ruby version directory.
Here is what my system shows when I run gem environment (I'm excluding the irrelevant parts):
- GEM PATHS:
- /Volumes/Data/nathan/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1
- /Volumes/Data/nathan/.gem/ruby/1.9.1
Any reason for having two locations? Curious minds want to know.
I think I figured out the answer to this question, so I'll post it.
Rbenv allows for a global and/or local version of ruby. So once a ruby is installed and managed via rbenv, you can declare it as a global ruby version used by your entire system.
Likewise, you can declare a local ruby version within a given directory (ex: a specific rails project).
The .gem file in your home path is used by the global ruby version, where as the one tucked away in the rbenv directory is used by the local ruby version.
Note, you can (for whatever reason) declare a local version that is the same as the global version. In that case, the local version will rely on the gem files that are in the deeper rbenv directory, instead of the ~/.gem directory.
Keep in mind that ruby version managers like rbenv and rvm are relatively recent creations. Before they existed, an admin user would usually install ruby in a system-wide location like /usr/local. But non-admins needed a place to install their own gems, since they didn't have write permission under /usr/local . So the rubygems creators decided to add a secondary gem path in the current user's home directory, which would have a similar structure to the system location.
Here's an example of what the gem paths looked like in the old days:
- /usr/local/lib/ruby/gems/1.9.1
- /Users/kelvin/.gem/ruby/1.9.1
There still may be machines where ruby is installed like this, and you still have that recourse of the automatic secondary gem path. Of course you can also add more paths using the GEM_PATH environment variable, but the auto one is nice for handling the common case.
If you have admin rights, or you use a version manager, you can just ignore the ~/.gem dir as an artifact, a relic of the past if you will.
- /Volumes/Data/nathan/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1
is from rbenv, so ruby looks for the gems rbenv installed.
- /Volumes/Data/nathan/.gem/ruby/1.9.1
Apparently, rbenv doesn't restrict itself to its own gems, but rather includes the gems from system ruby as well, but only the ones that are installed as user (via gem --user-install).

bundler and rvm: how should i best i package my current installed gems into my folder?

I've recently started using rvm (and bundler) and am in the process of boxing up a project so that everything needed for the project lives in the project folder (and hence in source control), enabling someone checking it out to fire it up straight away with no external dependencies.
So, i'm sitting in my project's root folder, in an rvm with a named gemset, with all the gems i need installed in the current gemset.
Using bundler, can i package all these gems into the project, so that when the project is checked out into a new environment (which will be in an identically named rvm & gemset) i can either
a) install the gems from the gems folder in the project (rather than from rubygems.org for example) or
b) use them directly out of that folder?
rvm and bundler seem to replicate each other's purpose/functionality to some degree and i'm a bit confused...
Grateful for any advice - max
You can use the bundle package command to do that.
You can check the documentation about it : http://gembundler.com/man/bundle-package.1.html

How do I retain installed gems after updating rubygems?

After a recent reinstallation of Ubuntu, I reinstalled RubyGems. The Ubuntu repository grabbed version 1.3.5. Later I found I need the latest version. So I installed the RubyGems update to get to version 1.3.7.
The trouble is, upon upgrading gem list returns only a small subset of all my originally installed gems. In the past, I've solved this by reinstalling all my gems following an upgrade, but this is troublesome and I hope to avoid this workaround now and in the future.
I tried adding an export GEM_HOME to my .bashrc file. It didn't work. gem list still doesn't list all my gems (even though I can find them on my computer in /var/lib/gems/1.8/gems. I also created a .gemrc yaml file and set the gemhome path. When I run gem env I can see that the home path is set, but still gem list doesn't return everything.
What's up with this?
This won't directly answer your question, but a lot of us use rvm to manage Ruby and gems. The benefit is it doesn't require us to mess with the system's Ruby installation and gems, leaving those alone for any OS routines needing a particular version of Ruby or a gem.
Since switching to rvm I've quit installing an updated version in /usr/bin/local too as rvm makes it so easy to keep my development versions separate from the system.
There are great reasons to tweak the system gems so I won't question why you might do so. I'm just tossing out the rvm thang as it might help solve your needs.

Resources