CUBE SUGAR CONTAINER

技術系のこと書きます。

Ruby: bundler のグローバル設定にデフォルト値を保存する

Bundler は Ruby のパッケージ管理 (vendoring) をするためのパッケージ。 このブログでも、以前 Ruby の開発環境を整える記事の中で取り扱ったことがある。

blog.amedama.jp

ただ、こいつはデフォルトだとパッケージをシステム環境にインストールしようとする。 もし異なる場所 (ディレクトリ) にインストールしたいときは --path オプションで指定しなきゃいけない。

なので、これまでは次のようなエイリアスをシェルの設定に追加して使っていた。

alias bi="bundle install --path=vendor/bundle"

こうすると Gemfile のあるディレクトリで bi と入力すると上記のコマンドが実行される。

$ bi

ただ、上記みたいなエイリアスを貼らなくても楽をする方法があるよ、というのが今回の趣旨。 具体的には、グローバルの設定にインストール先のパスをあらかじめ指定しておく。

今回使った環境は次の通り。

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.11.6
BuildVersion:   15G1108
$ ruby --version
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin15]
$ bundler --version
Bundler version 1.13.6

下準備

まずは gem コマンドを使ってシステム環境に Bundler をインストールする。

$ gem install bundler

続いて適当な作業ディレクトリで init サブコマンドを実行する。

$ bundle init

するとプロジェクトで使用するパッケージを羅列する Gemfile というファイルができる。

$ cat Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

# gem "rails"

ここに、ひとまずテスト用として sqlite3 を追加しておこう。 これは別の gem でも構わない。

$ echo "gem 'sqlite3'" >> Gemfile
$ cat Gemfile
# frozen_string_literal: true
source "https://rubygems.org"

# gem "rails"
gem 'sqlite3'

通常の使い方

まずは、いつも通りの使い方から。 install サブコマンドに --path オプションを指定して実行しよう。

$ bundle install --path=vendor/bundle
Fetching gem metadata from https://rubygems.org/...........
Fetching version metadata from https://rubygems.org/.
Resolving dependencies...
Installing sqlite3 1.3.12 with native extensions
Using bundler 1.13.6
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Bundled gems are installed into ./vendor/bundle.

すると、オプションで指定した vendor/bundle ディレクトリ以下に gem がインストールされる。

$ ls vendor
bundle

実は、上記を実行すると次のように .bundle/config という名前でプロジェクトの設定ファイルが保存されている。

$ cat .bundle/config
---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_DISABLE_SHARED_GEMS: "true"

使われる内容は config サブコマンドで確認することもできる。

$ bundler config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/Users/amedama/Documents/temporary/sample/.bundle/config): "vendor/bundle"

disable_shared_gems
Set for your local app (/Users/amedama/Documents/temporary/sample/.bundle/config): "true"

上記の確認ができたら、一旦設定とインストールされたディレクトリを削除しておこう。

$ rm -rf vendor .bundle

グローバル設定にデフォルト値を保存する

では、次に上記のような --path オプションを毎回指定しなくても良い方法について。

これには config サブコマンドで --global に対して path の設定を入れよう。

$ bundler config --global path vendor/bundle

すると、ユーザのホームディレクトリに Bundler の設定ファイルができる。

$ bundler config
Settings are listed in order of priority. The top value will be used.
path
Set for the current user (/Users/amedama/.bundle/config): "vendor/bundle"

デフォルト値が設定できたところで --path ディレクトリを指定せずに install サブコマンドを実行してみよう。

$ bundler install

すると --path でディレクトリを指定しなくても vendor/bundle ディレクトリにインストールされた。

$ ls vendor
bundle

これで毎回 --path オプションを指定する必要がなくなった。

グローバル設定をオーバーライドする

ちなみに、グローバル設定はプロジェクトのローカル設定でオーバーライドすることもできる。

試しに --local に対して path を別の値で指定してみよう。

$ bundler config --local path foo/bar
You are replacing the current local value of path, which is currently nil

すると、グローバル設定とローカル設定の両方がコンフィグとして見えるようになる。

$ bundler config
Settings are listed in order of priority. The top value will be used.
path
Set for your local app (/Users/amedama/Documents/temporary/sample/.bundle/config): "foo/bar"
Set for the current user (/Users/amedama/.bundle/config): "vendor/bundle"

disable_shared_gems
Set for your local app (/Users/amedama/Documents/temporary/sample/.bundle/config): "true"

この状態で install コマンドを実行してみよう。

$ bundler install

するとローカル設定で指定したディレクトリに gem がインストールされている。

$ ls foo
bar

このように、ローカル設定でグローバル設定をオーバーライドできることが分かった。

まとめ

  • Bundler で Ruby gems のパッケージ管理 (vendoring) ができる
  • ただ、毎回 --path オプションを指定するのがめんどい
  • そんなときはグローバル設定にデフォルト値を設定すると楽になる