20
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Gemfile.lockをLinuxとMacで分ける

Last updated at Posted at 2014-10-25

前置き

メリット

異なるOSでもgemが保証される。

  • 「OSごとに違うgemを入れなきゃ、でもそうするとGemfile.lockが衝突するからリビジョン管理から外そう」 ⇒ 知らぬ間にデプロイ先で不適切gemが使われる ⇒ 予期せぬ事態
    の、リスク解消。大事。

デメリット

bundleコマンドやWebrick起動がめんどくさくなる。

  • bundle install --gemfile=path/to/Gemfileしたり
  • cd path/to/Gemfileしてから実行しないといけなかったり
    • なぜかbundle install以外のbundleコマンドには--gemfileオプションがない。

RAILS_ROOTにGemfileが在る前提じゃないと動かないライブラリがあったりする。

  • ソースまで見て「だから動かないのかクソ・・・!」とか。

ハマる。

  • 自動デプロイとかで間違いなくハマる。しかも前例が見つからない。つらかった。

ので、導入・保守・効果コストを理解した上で行う。

ポイント

  • Gemfile.lockは、Gemfileが在る場所に作成される。
  • LinuxとMacで、Gemfile.lockのディレクトリを分ける。
    • GemfileもGemfile.lockもふたつ。
  • 環境変数RUBY_PLATFORMが、LinuxとMacで異なることを利用する。
    • Linuxだとlinux、Macだとdarwinという単語が入り込んでいる。

やり方

  • Gemfileの置き場所を、RAILS_ROOT直下ではない場所にする。
    • linux, darwinだけが違うディレクトリを2つ作る。たとえば、
      • gemfiles/darwin/
      • gemfiles/linux/
    • それぞれにGemfile, Gemfile.lockを配置する。
# 配置イメージ
├── README.md
├── Rakefile
├── app
├── bin
├── config
│   ├── application.rb
│   └── boot.rb
├── db
├── gemfiles
│   ├── darwin
│   │   ├── Gemfile
│   │   └── Gemfile.lock
│   └── linux
│       ├── Gemfile
│       └── Gemfile.lock
├── lib
├── log
├── public
├── spec
└── vendor
  • アプリケーションがbundleを正しく読み込めるよう、application.rbに追記する。
config/application.rb
require File.expand_path('../boot', __FILE__)
 
require 'rails/all'
require 'bundler' # 追記
 
# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)
 
platform = RUBY_PLATFORM.match(/(linux|darwin)/)[0].to_sym # 追記
Bundler.require(platform) # 追記

...
  • boot.rbにも追記する。
config/boot.rb
#ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) # もともとあるのでコメントアウト
platform = RUBY_PLATFORM =~ /darwin/ ? 'darwin' : 'linux' # 追記
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../gemfiles/#{platform}/Gemfile", __FILE__) # 追記
  • 【一方のGemfile】分けたいgemに、ifやgroupを追加する。
gemfiles/darwin/Gemfile
...
# for Mac
group :darwin do
  gem 'libv8', '3.16.14.3' if RUBY_PLATFORM=~ /darwin/
end

# for Linux
group :linux do
  gem 'libv8', '3.3.10.4' if RUBY_PLATFORM=~ /linux/
end
...

if RUBY_PLATFORM=~ /linux/
  gem 'therubyracer', '0.10.2', platforms: :ruby
else
  gem 'therubyracer', platforms: :ruby
end
...
  • 【もう一方のGemfile】下記のみにする。
gemfiles/linux/Gemfile
eval(Pathname(File.expand_path('../../darwin/Gemfile', __FILE__)).read) # linuxとdarwinは適宜。

動作確認

bundle install 例

bundle install --gemfile=gemfiles/darwin/Gemfile # Mac
bundle install --gemfile=gemfiles/linux/Gemfile # Linux

それぞれ正常に読み込まれ、別々にGemfile.lockが更新されたらOK!
※最初は、Gemfile.lockを退避なり削除なりしてから実行したほうがよいかも。

bundle list 例

# Mac
cd gemfiles/darwin
bundle list

# Linux
cd gemfiles/linux
bundle list

bundle update等々も同様。ちなみにbundle installもこれで出来る。

最後に

  • 開発はMac、デプロイ先はCentOS、だからこの努力はきっと必要なはず・・・!
  • Gemfileってただのrubyスクリプトなんだなぁと。
  • Gemfile読み込みは、シンボリックリンクにしていたこともあるが、何かの拍子に何故か実ファイルになってしまったり、Winが入ってきたら対応できないよなぁと思ったりで、やめた。
  • 思い出しながら書いているので抜け漏れあったらごめんなさい。
20
18
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?