複数のプロジェクトでGemfileを共有する方法

require 'pathname'
instance_eval (Pathname(__FILE__)+"another_project/Gemfile").read)

などとします。

なんでこんなことやりたいの?

Railsのプロジェクトをテストするためのプロジェクトを用意して、そっちでもRailsのモデルを読みたいのです*1。さらに、テストプロジェクトのためのライブラリがあって、そっちはRailsのほうのGemfileには含めたくない*2

具体的には、FrankのテストをRailsとわけて管理したくて、さらにテストの方でiOSシミュレータの起動のためにsim_launcherが必要。

最初こうしました

load "another_project/Gemfile"

これはうまく行きません。loadすると、普通のトップレベルと同じ扱いになるので、gemとかのメソッドがないと言われます。

ではinstance_evalだ

instance_eval Pathname("another_project/Gemfile").read

これでひとまずはうまくいきます。

もう一つ落とし穴

実はテストの中で、

system("cd another_project && bundle exec rails server")

している場所がありました。

これがなんかうまく行かない。どうも、bundle execされたRailsがカレントディレクトリ(Railsプロジェクト)のGemfileではなく、テストプロジェクト(一個上のディレクトリ)のGemfileを読んでいるように見えます。

こういうわけで最初の形に落ち着きました。

バグじゃねーの?

ばぐってんじゃねーの?と思って、先日のHeroku MeetupでTerence Leeに聞いたのですが、これが意図された挙動なのだそうです。bundlerは、上のディレクトリまでGemfileを探しにいって、一番上のGemfileを使います。(しかし本当に便利なのかなこれ。)

Gemfileを指定するには、

system("BUNDLE_GEMFILE='./Gemfile' bundle exec rails server")

などとして指定すればokです。

*1:今回は標準的なRailsのテストではないので、Railsプロジェクトにはこのテスト群を含めません。

*2:これがないならば、symlinkするのが楽だと思います。