君の瞳はまるでルビー - Ruby 関連まとめサイト

ライブラリ(gem)のパス追加

最終更新: 2015-03-31 (火) 21:53:17 (1571d)

イディオム

基本形

ライブラリ(gem)を読み込む(=require する)際に検索対象となるパスを追加したい場合、require を実行する前に以下の処理を実行します。

$:.unshift('パス文字列')

パス文字列は、

  • 絶対パス
  • コマンド実行時ディレクトリからの相対パス

どちらでも構いません。

また、以下の書き方は全て同じ意味になります。

# $LOAD_PATH を使った場合
$LOAD_PATH.unshift('パス文字列')

# $-K を使った場合
$-K.unshift('パス文字列')

$: と $LOAD_PATH と $-K は Kernel モジュールが定義する定数です。

詳細は Ruby の「Kernel モジュール」のリファレンスを参照してください。

ライブラリの検索パスを追加する際によく使うイディオムを紹介します。

実行時のパスに左右されないようにする

単純に相対パスを使ってしまうと、別のパスから起動した場合、動かなくなってしまいます。

ライブラリの検索パスの追加方法を工夫し、起動プログラムの最初に以下の処理を書くことで、プログラム実行時のパスに左右されないようにできます。

$:.unshift(File.dirname(File.expand_path(__FILE__)) + '起動プログラムからの相対パス文字列')

File.dirname(File.expand_path(__FILE__)) は、実行中のソースコードがあるディレクトリの絶対パスです。

__FILE__ は Ruby 標準の疑似変数です。リファレンスの「変数と定数」を参照してください。

このイディオムを利用することの利点は、プログラムをどこから起動しても良くなることです。

例えば、

  • 開発中は起動プログラムが置いてあるパスから相対パスで実行していた。
    • ruby sample.rb
  • 稼動時は起動プログラムを絶対パスで実行することになった。
    • ruby /path/sample.rb

といった状況に強くなります。

外部プログラムから起動するような場面で役に立ちます。

Ruby 1.8/1.9/2.0 のライブラリのパスの扱いを吸収する

起動プログラムの最初に以下の処理を書くことで、Ruby 1.8/1.9/2.0 の挙動の違いを吸収できます。

require 'rubygems'

$:.unshift(File.dirname(File.expand_path(__FILE__)))

Ruby 1.8/1.9/2.0には検索パスの扱いに違いがあります。

  • Ruby 1.8 系
    • rubygems で管理しているライブラリが検索パスに入っていない。
      • require 'rubygems' が検索パスを設定してくれる。
    • プログラムを起動した際の関連とディレクトリ(".")がライブラリの検索パスに入っている。
      • 重複して追加しても問題ない。
  • Ruby 1.9/2.0 系
    • rubygems で管理しているライブラリが検索パスに入っている。
      • require 'rubygems' は不要だが、呼び出しても弊害は無い。
    • プログラムを起動した際のカレントディレクトリ(".")がライブラリの検索パスに入っていない。
      • $:.unshift で起動プログラムの絶対パスをライブラリの検索パスに追加する。

このイディオムを利用することで、Ruby 1.8/1.9/2.0 の違いを意識せずに済みます。

特定バージョンのライブラリを使う

環境にあるライブラリではなく、特定バージョンのライブラリを使いたい場合、

  • 使いたい特定バージョンのライブラリを相対パス上に配置する。
  • 上記の相対パスを unshift でライブラリの検索パスに追加する。

とします。

例として、バージョン 1.0.0 の xyz というライブラリを使いたいという場合を想定します。

その場合、ファイル構成を以下のようにし*1*2

  • 起動プログラム.rb
  • verndor
    • xyz-1.0.0

起動プラグラムに以下の記述を追加します。

$:.unshift(File.dirname(File.expand_path(__FILE__)) + '/vendor/xyz-1.0.0/')

ポイントは unshift でライブラリの検索パスを追加している点です。

require は、ライブラリの検索パスを順番に検索していき、一番最初に見つかったものを読み込みます。

unshift により配列の先頭に検索パスを追加することで、 環境に入っているライブラリよりも、特定バージョンのライブラリを優先的に検索するよう指示することになります。

push でライブラリの検索パスを追加した場合、 追加したパスが検索されるのは後になってしまい、 環境に既に入っているライブラリの方が先に見つかってしまいます。

参考

専用ツールがあります。

このツールにライブラリ関連の管理を任せることができます。

コメント

本ページの内容に関して何かコメントがある方は、以下に記入してください。

最新の10件を表示しています。 コメントページを参照

  • よくpushとunshiftの別々を見かけますが、unshiftの優位点はありますか? -- 初心者 2013-02-01 (金) 00:49:18
  • その疑問よくわかります。unshift より push の方が配列に対する操作は一般的ですよね。同じ配列への追加ならなぜ push ではなく unshift をわざわざ使うのかという疑問は最もだと思います。 -- トゥイー 2013-02-01 (金) 01:38:15
  • 「優位点」というと少し語弊がありますが unshift には「特別な意味」が込められています。 -- トゥイー 2013-02-01 (金) 01:39:04
  • require は gem を LOAD_PATH 順に検索していきます。「同じ名前のファイルが検索パス上に存在した場合にどちらが読み込まれるか?」となったときに unshift での検索パスの追加には「最後に追加した検索パスを優先して見て欲しい。」という意味が加わります。push だと追加した検索パスを見るのは最後になるので、そのような意味合いを持ちません。 -- トゥイー 2013-02-01 (金) 01:40:08
  • unshift と push の違いが出るのは、同じ名前のファイルが検索パス上に複数存在する場合だけです。そのような場合、通常は「後に追加した検索パスの方を優先的に見て欲しい」となることが多いので unshift に意味が出てきます。 -- トゥイー 2013-02-01 (金) 01:57:35
  • push と unshift の意味の違いをちゃんと知っていれば通常はどちらでも構いません。特殊な場合には、その意味を理解した上で使い分けてください。 -- トゥイー 2013-02-01 (金) 02:06:42
  • 返信遅れてしまいましたが、丁寧な解説感謝します。とてもわかりやすかったです。 -- 初心者 2013-02-07 (木) 02:34:58
  • いえいえ、こちらこそ。今回、質問があった内容を踏まえて少し内容を書き換えさせてもらったので、それも参考にしていただければと思います。 -- トゥイー 2013-02-08 (金) 22:44:34
お名前: