Skip to content

Instantly share code, notes, and snippets.

@arairait
Last active August 3, 2017 08:00
Show Gist options
  • Save arairait/3506a386fd32e7e15497095c33ca857d to your computer and use it in GitHub Desktop.
Save arairait/3506a386fd32e7e15497095c33ca857d to your computer and use it in GitHub Desktop.
bundlerの使い方「自分用」ベストプラクティス

一般に gem の管理は bundler を使うことがよいとされている

その理由:

  • プロジェクトごとに、使用する gem とそのバージョンを管理できる
  • Gemfile, Gemfile.lock をコミットしておくことで git clone && bundler install ですぐに必要な gem が整う

しかし、自分の環境では不便が多い(あくまで自分の場合)

  • 多くの gem は全プロジェクトで共通でよい
    • 例:pry, awesome_print, digest, logger など
    • バージョンアップを即適用するべきものも少なくない(opensslなど)
    • 今後 Ruby の添付ライブラリの gem 化が促進されるので、そのようなケースはますます増える
  • .rb を実行するのに毎回 cd PROJECT_DIR && bundle exec hoge.rb が面倒
    • とくに cron で実行するもの

そこで自分的ベストプラクティス

  • gem を厳選して global にインストールする。バージョン依存しないと思われるもの。
    • bundler, pry, awesome_print, json, openssl, rack, passenger
  • 各.rb では以下のように記述する
    require 'global_gem1'
    require 'global_gem2'
      :
    require 'bundler/setup' # これ以降 Project 管理の gem を require する
    require 'gem_in_this_project1'
    require 'gem_in_this_project2'
      :

これにより、不便な点のほとんどが解消される(唯一 cd PROJECT_DIR しないといけない点は残る)。

この運用への予想される意見とそれに対する反論

「gem が global かどうかをスクリプト側で記載するのはメンテナンス性に欠ける」
→ 逆に、同じ gem でもプロジェクトで管理するかシステムに任せる(=global gem を使用する)かをスクリプトで制御できる。

「これでは、git clone & bundle install ですぐ動作しない。global gem がシステムにインストールされているかは分からない」
→ それはその通り。しかし元々「すべての gem をプロジェクトごとに持ちたくない」がこの運用のモチベーションなので、それはトレードオフ。

「disable-shared-gems を無効にすればいいんじゃね?」
→ 確かに disable-shared-gems を無効にすると Gemfile に指定した gem がシステムにあればインストールはスキップされてシステムのgemを使う。
しかしそれだと「このプロジェクトではこのgemをプロジェクトローカルに持っておきたい」というコントロールができない。

「rbenv使ってるなら、いっそのこと bundler 使わなくても・・・」
→ ううむ、実際 Ruby バージョンごとに gemset 持っていれば非互換性のためにスクリプトが動作しないということはまず起きないだろう・・・。
しかし他のサーバーで動かそうとしたとき git clone && bundle install すればよいだけなのはやっぱり楽だ。

問題

  • sinatraアプリをpassengerで走らせているのだが、passengerは自動的にbundle execするのでbundler/setupする前のrequire(global gemを呼び出すもの)がエラーになってしまう
  • sinatraアプリだけはすべてgemをプロジェクト管理にするしかない。が、そんな使い分けは面倒だしシンプルじゃない・・・。

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment