Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Homebrew install Ruby keg-only can't find gem

How do I get irb to work after installing Ruby with Homebrew?

When I try to run irb, I get an error:

$ irb
Traceback (most recent call last):
    2: from /usr/local/opt/ruby/bin/irb:23:in `<main>'
    1: from /usr/local/lib/ruby/site_ruby/2.6.0/rubygems.rb:302:in `activate_bin_path'
/usr/local/lib/ruby/site_ruby/2.6.0/rubygems.rb:283:in `find_spec_for_exe': can't find gem irb (>= 0.a) with executable irb (Gem::GemNotFoundException)

I tried:

$ brew link ruby
Warning: Refusing to link macOS-provided software: ruby
If you need to have ruby first in your PATH run:
  echo 'export PATH="/usr/local/opt/ruby/bin:$PATH"' >> ~/.bash_profile

For compilers to find ruby you may need to set:
  export LDFLAGS="-L/usr/local/opt/ruby/lib"
  export CPPFLAGS="-I/usr/local/opt/ruby/include"

I have the lines below at the top of my /etc/paths file:

/usr/local/bin
/usr/local/opt/ruby/bin
/usr/local/lib/ruby/gems/2.6.0/bin

irb doesn't show up in the output of gem list, but:

$ find /usr/local -name irb
/usr/local/lib/ruby/2.6.0/irb
/usr/local/Cellar/ruby/2.6.0_1/bin/irb
/usr/local/Cellar/ruby/2.6.0_1/lib/ruby/2.6.0/irb
/usr/local/Cellar/ruby/2.6.0_1/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb
/usr/local/Cellar/ruby/2.6.0_1/share/ri/2.6.0/system/lib/irb

I'm also having a similar issue with ri & rdoc.

like image 218
ma11hew28 Avatar asked Jan 27 '19 23:01

ma11hew28


2 Answers

Run: gem install irb and you now good to go.

like image 106
Eric Guo Avatar answered Oct 05 '22 04:10

Eric Guo


Assuming you're using Homebrew Ruby...

The irb executable is located at:

/usr/local/opt/ruby/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb

You can use that line directly, symlink it into your $PATH, alias it, or whatever.


Alternatively, you may patch /usr/local/opt/ruby/bin/irb around line 22.

# patch
class Gem::BasicSpecification
  def self.default_specifications_dir
    File.join(Gem.private_dir, "specifications", "default")
  end
end
# /patch

# Next line looks like this. Don't change this.
# if Gem.respond_to?(:activate_bin_path)

You may do the same in /usr/local/opt/ruby/bin/ri and /usr/local/opt/ruby/bin/rdoc to patch those commands as well.

Why?

See https://github.com/Homebrew/homebrew-core/blob/955497722b9bf65069957b0e7c903b96939cdd99/Formula/ruby.rb#L112

The Homebrew Ruby formula assumes all gems will be installed in the "global gem directory" /usr/local/lib/ruby/gems/2.6.0/. So when you uninstall-reinstall Homebrew Ruby, the gems stick around - you don't have to re-install them as well (kinda annoying since I have gems installed for Ruby versions I don't even have installed anymore, but that's another issue).

But Ruby's default gems aren't in the global gem dir. They're inside the Ruby installation dir (what the Homebrew formula refers to as the private_dir) : /usr/local/opt/ruby/lib/ruby/gems/2.6.0/.

So Homebrew Ruby can't find them.

Homebrew patches Rubygems, so this snippet patches Rubygems again, but deeper. You can also patch-patch like this:

module Gem
  def self.default_dir
    private_dir  
  end
end

But default_dir is used in other places and I didn't want to break anything.

like image 20
eddroid Avatar answered Oct 05 '22 06:10

eddroid