Managing gems with Bundler on macOS

Managing gems with Bundler on macOS

Installation

Attempt to install bundler will fail as only root have write access to this part of the operating system. Using sudo is not a good choice. macOS depends on gems installed there and we do not want to risk violating system integrity.

wojtek@MacBook:~$ gem install bundler
ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory.

Instead, we ought to install bundler in another location, preferably /usr/local/bin directory for non-essential command binaries for all users1. Since this directory does not exist on macOS by default, we will create it manually.

wojtek@MacBook:~$ ls -l /usr | grep local
drwxr-xr-x    3 root  wheel     96 Jun  5 20:30 local
wojtek@MacBook:~$ sudo mkdir /usr/local/bin

Permissions must allow write access for users of admin group. This way they will be able to install software in /usr/local/bin without using sudo.

wojtek@MacBook:~$ sudo chown `whoami`:admin /usr/local/bin/
wojtek@MacBook:~$ chmod g+w /usr/local/bin/
wojtek@MacBook:~$ ls -l /usr/local/
total 0
drwxrwxr-x  2 wojtek  admin  64 Jun 10 17:01 bin

Installation succeeded without any file permission errors.

wojtek@MacBook:~$ gem install bundler --user-install --bindir /usr/local/bin/
Fetching: bundler-1.16.2.gem (100%)
Successfully installed bundler-1.16.2
Parsing documentation for bundler-1.16.2
Installing ri documentation for bundler-1.16.2
Done installing documentation for bundler after 7 seconds
1 gem installed

Bundle and bundler binaries were installed in /usr/local/bin/, and bundler ruby gem in ~/.gem/ruby/2.3.0/gems/.

wojtek@MacBook:~$ ls -l /usr/local/bin/
total 16
-rwxr-xr-x  1 wojtek  admin  525 Jun 10 17:17 bundle
-rwxr-xr-x  1 wojtek  admin  526 Jun 10 17:17 bundler
wojtek@MacBook:~$ ls -l ~/.gem/ruby/2.3.0/gems/
total 0
drwxr-xr-x  10 wojtek  staff  320 Jun 10 17:19 bundler-1.16.2

Usage

Defining dependencies

Specify your dependencies in a Gemfile in your project’s root:

source "https://rubygems.org"

gem "json"
gem "jekyll"
gem "jekyll-sitemap"
gem "jekyll-feed"
gem "jekyll-paginate"
gem "jekyll-gist"

Installing dependencies

bundle install installs the dependencies specified in your Gemfilein the same location as gem install command. We aim keep them in a separate directory, and --path option is going to help us with that.

After installation completes bundler creates hidden .bundle directory with config file inside of it. We will place our dedicated dependencies directory in .bundle as well, so when we finally decide to delete the project the dependencies will get deleted along with it.

wojtek@MacBook:wnagrodzki.com$ bundle install --path '.bundle/dependencies'
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/.
Resolving dependencies...
Fetching public_suffix 3.0.2
Installing public_suffix 3.0.2
...
Bundle complete! 6 Gemfile dependencies, 35 gems now installed.
Bundled gems are installed into `./.bundle/dependencies`

Do not forget to commit Gemfile and Gemfile.lock. Add .bundle/dependencies directory to .gitignore.

Executing commands

To execute a command in the context of the bundle precede it with bundle exec.

wojtek@MacBook:wnagrodzki.com$ bundle exec jekyll serve

Bundler will look into config file for the path dependencies are installed. See BUNDLE_PATH in the listing below.

wojtek@MacBook:wnagrodzki.com$ cat .bundle/config
---
BUNDLE_PATH: ".bundle/dependencies"

Updating dependencies

To update dependencies run bundle update.

For more information refer to bundler documentation.

  1. /usr/local/bin purpose is defined by Filesystem Hierarchy Standard