xxxcaqui.log

ツッコミお待ちしています

Gemfileについて調べてみた

Gemfileについてよくわかってなかったので調べてみた。

そもそもGemfileって?

Bundler用の設定ファイル。

BundlerはGemfileの記述にしたがって、gemの依存関係を示したGemfile.lockを生成する。

じゃあ、Bundlerって何さ?

アプリケーションで使用するgemのバージョン管理を行うプログラム。

「お前が書いたコード動かないんだけど?」
「ハァ? 俺の環境では動いてるし。バージョン違うんじゃねーの? 死ねよ」

ってならないためのツール。

Railsをはじめ、SinatraやRubyMotionでも使われている。*1

ちなみに、Bundlerの公式サイトにはこう書いてある。

The best way to manage your application's dependencies

ベストらしいので使わない手はない。

source

gemが置いてある場所を指定する。
Bundlerはこのsourceにgemのコードを取りに行く。

普段、Railsを使っていると自動挿入されるのであまり意識しないが、Gemfileには最低1つのsourceが指定されていないといけない。

ちなみに、RailsデフォルトのGemfileだとこう。

source 'https://rubygems.org'

さらに、これはURL文字列以外にもシンボルで書くことができる。*2

String Symbol
http://rubygems.org :rubygems
http://gems.rubyforge.org :rubyforge
http://gemcutter.org :gemcutter

ruby

アプリケーションを実行するRubyのバージョンを指定できる。

ruby '1.9.3'

ハッシュの{key: value}記法を使っている場合などは指定しておいたほうがいいかもしれない。

ちなみに、引数にハッシュを渡すことによって、Ruby処理系を指定することができる。

ruby '1.9.3', engine: "jruby", engine_version: "1.6.7"

gem

gemコマンド*3で使用するgemを指定する。

例えば、アプリケーションでnokogiriを使いたい場合、次のように書く。*4

gem 'nokogirl'

バージョン管理

Bundlerはただのgemインストーラではなくバージョン管理ツール*5なので、このgemコマンドは第2引数にバージョンを取れる。

gem "nokogiri"             # 最新版を入れる
gem "rails", "3.0.0.beta3" # 3.0.0.beta3で固定
gem "rack",  ">=1.0"       # 1.0以降のバージョンに制限
gem "thin",  "~>1.1"       # 1.1以降2.0以前のバージョンに制限
"~>"の挙動*6
記述 対象バージョン
~>1.1 2.0 > version >= 1.1
~>1.1.2 1.2.0 > version >= 1.1.2

ちなみに、gemの名前はStringで渡さなければならない。*7

他のオプション

gemコマンドは他にもいろいろなオプションをハッシュで渡せます。

ソースの取得先を指定
gem "nokogiri", git: "git://github.com/tenderlove/nokogiri.git", branch: "1.4"
gem "nokogiri", path: "~/sw/gems/nokogiri"
自動的に読み込むファイルを指定
gem "nokogiri", require: "nokogiri" # default
gem "redis", require: ["redis/connection/giredis", "redis"]
gem "wirble", require: false # autorequireしない
gemコマンドのオプション一覧
オプション名 内容
group,groups gemをインストールするグループを指定する。*8
git,gist,github ソースのGitリポジトリを指定する。
branch,tag 指定したGitのブランチ・タグを指定する。
path ローカルにあるgemのパスを指定する。
require autorequireするgemを指定する。falseでautorequireしない。
name  
ref  
submodules  
platform,platforms  
type  

group

groupコマンドではgemをインストールする環境を指定できる。

group :development, :test do
  gem "rspec-rails"
  gem "cucumber"
end

のように設定した上で本番環境で

$ bundle install --without development test

とすると、developmentグループ及びtestグループのgemを除いてインストールを行うことができる。

こうなると、

$ bundle install --only test

とかが欲しいところだが、そういったオプションは用意されていない模様。

その他Bundlerのオプション

よく使うのはこんな感じ。

bundle exec command

$ bundle exec rake db:migrate

Gemfileに記載されたコンテキストでコマンドを実行できる。*9

bundle install --path dir_name

$ bundle install --path vendor/bundle

Bundlerによってインストールするgemをデフォルト($BUNDLE_PATHまたは$GEM_HOME)のディレクトリ以外にする。一度指定するとBundlerがそのディレクトリを覚えてくれるため、次回以降は指定不要。

bundle install --system

$ bundle install --system

上記の--pathの逆。システムのデフォルトディレクトリにgemをインストールする。

まとめ

以上、いろいろ調べてみた*10けど、groupの使い方がよくわからない。

Railsでよく使う:development, :test以外にも任意のグループを設定できるみたい*11だけど、どうやって使うんだろうか……。

*1:Bundler公式サイトには書いてなかったけどPadrinoでも使ってるっぽい。

*2:ただし、引数が:rubygems, :rubyforge, :gemcutterのいずれかの場合、どれを指定してもhttp://rubygems.orgを参照する。

*3:コマンドと書いたが、実際にはBundler::Dslクラスのインスタンスメソッド。sourceコマンドなども同じ。

*4:nokogiriはnokogirlでも入ります。俺のためにHTMLをパースしてくれるnokogirlたん萌え。

*5:こう書くとGitとかと紛らわしい。なんと呼べばいいんですかね?

*6:ステキすぎて鼻血でそう。

*7:シンボルで書くと、エラーを吐かれます。

*8:グループごとにまとめる場合はgroupコマンドのブロックの中に書いたほうがキレイ

*9:「rakeのバージョンがおかしい」とか言われたときに使うと高確率で幸せになれる。

*10:足りないアタマを使ってGitHubのコードも読んでみた。

*11:Bundlerのサンプルコードには:ciとかあった。