!はじめに
 #contents
 
 *はじめに [#sf691330]
 
 Rubyパッケージの伝統的なインストーラとして[[青木さんのsetup.rb>http://i.loveruby.net/ja/projects/setup/]]があります。著名なRubyのパッケージ管理ツールであるRubyGemsでさえ、インストールする方法は
 
  ruby setup.rb
 
 です。Ruby on Railsを理解する前にRubyGemsを理解する前にsetup.rbを理解してみましょう。その前にRubyを理解する必要があるんじゃないかって?それはすでに[[青木さんの大著>http://i.loveruby.net/ja/rhg/book/]]があるので小生の出る幕はありません。
 です。Ruby on Railsを理解する、前にRubyGemsを理解する、前にsetup.rbを理解してみましょう。その前にRubyを理解する必要があるんじゃないかって?それはすでに[[青木さんの大著>http://i.loveruby.net/ja/rhg/book/]]があるので小生の出る幕はありません。
 
 *起動部分 [#tc6d6dab]
 
 ではまず、ruby setup.rbとした時に何が起こるかを見てみましょう。実際のコードでは例外処理があるのですが見やすさのためにそこら辺のコードは省きます。
 
  if $0 == __FILE__
    ToplevelInstaller.invoke
  end
 
 $0は実行中のファイル名、__FILE__は現在のソースファイル名です。この2つは似ているようで違います。論より証拠です。次の2つのスクリプトがあったとします。
 
 foo.rb
  puts "$0?t:#{$0}"
  puts "__FILE__:#{__FILE__}"
  
  if $0 == __FILE__
    puts 'foo.rb'
  end
 
 bar.rb
  require 'foo'
  
  puts "$0?t:#{$0}"
  puts "__FILE__:#{__FILE__}"
 
 foo.rbを実行すると以下のように表示されます。
 
  $ ruby foo.rb
  $0      :foo.rb
  __FILE__:foo.rb
  foo.rb
 
 bar.rbを実行すると以下のように表示されます。
 
  $ ruby bar.rb
  $0      :bar.rb
  __FILE__:./foo.rb
  $0      :bar.rb
  __FILE__:bar.rb
 
 $0は変わらないけど__FILE__は変わります。__FILE__はRubyインタプリタが今まさに読んでいるファイルです。一方、$0はRubyインタプリタ起動時に指定されたスクリプトです。
 
 さて、以上の説明およびfoo.rbの実行結果を見ていただくとご理解いただけると思いますが、
 
  if $0 == __FILE__
    何とか
  end
 
 というのはスクリプトが直接実行されたときに実行したいコード(ライブラリとして呼ばれたときは実行して欲しくないコード)を入れておくためのイディオムです。
 
 *ToplevelInstaller.invoke [#c798b1a5]
 
 前置きが長くなってしまいましたが、起動時に呼ばれるToplevelInstaller.invokeに進みましょう。ToplevelInstaller.invokeは以下のようになっています。
 
  def ToplevelInstaller.invoke
    config = ConfigTable.new(load_rbconfig())
    config.load_standard_entries
    config.load_multipackage_entries if multipackage?
    config.fixup
    klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller)
    klass.new(File.dirname($0), config).invoke
  end
 
 一行ずつ読んでいきましょう。
 
 *ToplevelInstaller.load_rbconfig [#z85024e7]
 
 まず、ToplevelInstaller.load_rbconfigです。
 
  def ToplevelInstaller.load_rbconfig
    if arg = ARGV.detect {|arg| /?A--rbconfig=/ =~ arg }
      ARGV.delete(arg)
      load File.expand_path(arg.split(/=/, 2)[1])
      $".push 'rbconfig.rb'
    else
      require 'rbconfig'
    end
    ::Config::CONFIG
  end
 
 まあそんな感じかなというところですが注目すべきは以下の一行です。
 
  load File.expand_path(arg.split(/=/, 2)[1])
 
 というか解説したいところが2つあるので二行に分けましょう。
 
  path = arg.split(/=/, 2)[1]
  load File.expand_path(path)
 
 一行目、普通ならsplit(/=/)とだけしてしまいそうですがオプション第2引数で分割数を2に限定しています。これにより、
 
  --rb-config=a=b.rb
 
 としていても適切にa=b.rbが読み込まれます。そんな変なファイル指定するなというところですがこういう細かい配慮がされていると好感が持てます。
 
 次に二行目、File.expand_pathを使って相対パスを絶対パスにしています。これにより、a.rbと指定した場合にスクリプト検索パス中にa.rbがあった場合に誤って読まれてしまうということがなくなります。広く使ってもらおうというコードはこういう配慮をすべきだなと痛感させられます。
 
 rbconfig.rbって何?という方のために書いておくとrbconfig.rbとはRubyインストール時に生成されるファイルでライブラリのディレクトリはどこかということが書いてあります。setup.rbはこのファイルを使うことでライブラリのインストール先を決定しています。
 
 

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS