Using Bundler with System Ruby
I just fixed my system configuration so that gem install
works. I install Bundler with gem install bundler
. I then go to my project directory and use Bundler to install my project’s dependencies:
$ bundle
Fetching gem metadata from https://rubygems.org/...........
Following files may not be writable, so sudo is needed:
/Library/Ruby/Gems/2.3.0
/Library/Ruby/Gems/2.3.0/build_info
/Library/Ruby/Gems/2.3.0/cache
/Library/Ruby/Gems/2.3.0/doc
/Library/Ruby/Gems/2.3.0/extensions
/Library/Ruby/Gems/2.3.0/gems
/Library/Ruby/Gems/2.3.0/specifications
Fetching public_suffix 3.0.3
Your user account isn't allowed to install to the system RubyGems.
You can cancel this installation and run:
bundle install --path vendor/bundle
to install the gems into ./vendor/bundle/, or you can enter your password
and install the bundled gems to RubyGems using sudo.
Password:
What the?… But I had just fixed the problem! Apparently Bundler has its own ideas about where to install gems.
It’s interesting (read: completely dangerous and irresponsible) that Bundler tells me to install gems using sudo
. It’s even in its documentation! And yet, Bundler places me at the password prompt! Fortunately I already know I shouldn’t do this.
Bundler also suggests using the path
option to install gems in the local folder, like node_modules
. But let’s skip this for now. Let’s fix Bundler so that gems are installed in a common folder and shared between projects.
In my previous post on using System Ruby, I used gem env
to understand my Ruby environment. Now, I can use a similar command to understand my Bundler environment:
$ bundle env
## Environment
Bundler 2.0.2
Platforms ruby, universal-darwin-17
Ruby 2.3.7p456 (2018-03-28 revision 63024) [universal.x86_64-darwin17]
Full Path /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby
Config Dir /Library/Ruby/Site
RubyGems 2.5.2.3
Gem Home /Library/Ruby/Gems/2.3.0
Gem Path ~/.gem/ruby/2.3.0:/Library/Ruby/Gems/2.3.0:/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/gems/2.3.0
User Path ~/.gem/ruby/2.3.0
Bin Dir /usr/local/bin
Tools
Git 2.24.1
RVM not installed
rbenv not installed
chruby not installed
## Bundler Build Metadata
Built At 2019-12-15
Git SHA 2760d72d3
Released Version true
## Gemfile
Some output omitted for brevity
PLATFORMS
ruby
BUNDLED WITH
2.0.2
Lots of interesting information here. The lines most relevant to my current predicament are these:
Gem Home /Library/Ruby/Gems/2.3.0
User Path ~/.gem/ruby/2.3.0
Notice that these are exactly the same paths that gave me trouble previously. Once again, something is complaining that it can’t write to /Library/Ruby/
. But as we saw last time, I have the necessary write permissions inside the home directory (~
). And just like there was a way to tell Ruby to always use the user directory, there’s also a way to tell Bundler the same. There are two environment variables that can be used for this effect: $BUNDLE_PATH
and $GEM_HOME
. All that I need then is to create a .profile
dotfile in the home directory with the following content:
export GEM_HOME=~/.gem/ruby/2.3.0/
After reloading the .profile
for the changes to take effect I can retry the previous command:
$ bundle
Fetching gem metadata from https://rubygems.org/...........
Bundle complete! 4 Gemfile dependencies, 28 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
And it works!
At this point my .profile
looks like this:
export GEM_HOME=~/.gem/ruby/2.3.0/
export PATH=~/.gem/ruby/2.3.0/bin:$PATH
The repetition can be fixed with some basic bash interpolation:
export GEM_HOME=~/.gem/ruby/2.3.0/
export PATH=$GEM_HOME/bin:$PATH
And the final solution can be made dynamic with some Ruby magic:
export GEM_HOME="$(ruby -e 'puts Gem.user_dir')"
export PATH="$GEM_HOME/bin:$PATH"