Rubyを学び始めてそんなに経っていませんが、Rubotyへの興味とともにRuboty のコードリーディングで Ruboty の仕組みを理解すると共に Ruby の設計・実装の定石を学ぶ #rubotyの記事でRubotyのコードリーディングを始めました。
仕事以外でコードを読むことはあまりしなかったのですが、始めてみるととても勉強になることに気がつきました。
1.自分の知らないRubyの使い方を知れる。
2.プログラムの構造など参考になる。
などが主な点でしょうか。しかし自分だけの独学だと限界があると思いますが、コードリーディングによって幅が広がると思います。
では早速読んでいきましょう。
ちなみにとても遅いペースでいきます。知らないことがたくさんですから!
bin/ruboty
# !/usr/bin/env ruby
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "ruboty"
Ruboty::CommandBuilder.new(ARGV).build.call
env
1行目は、**シバン(shebang)**というそうです。cgiでよく見るのですが、#!/usr/bin/perlとか#!/bin/shとか書かれているもので、どのシェルで実行するか指定するものです。
しかし上記のようなパターンは始めてみました。調べてみるとrubyでよくつかわれる形式のようです。
envは環境変数を設定して、プログラムを実行するコマンドのようです。
結局はrubyで実行するよということですが、envを指定することで環境変数が設定されるため、上記のperlやshのようにフルパスを記述する必要がないため使われているようです。cgiでは環境によってシバンが変える必要があることが多々あり、面倒だった記憶がありますが、それを解決した形になります。
$LOAD_PATH
rubyではlibなどロードするパスが格納されているようです。こういった変数は知らないものはずっと知らないことも多い気がします。
unshift
これは配列の頭に要素を追加するメソッドです。つまり上記の$LOAD_PATHは、配列ということになります。
File.expand_path(相対パス,基準のパス)
絶対パスを返すメソッドです。
__FILE__
実行中のプログラムのファイル名が格納されている変数です。
$LOAD_PATHから__FILE__までの説明を合わせると、その行の命令は、rubyで使うlibのパスにrubotyのディレクトリにあるlibのパスを追加していることになります。モジュールを分割してロードする必要がある時は、よく使いそうです。
もう少し調べてみると、__FILE__はファイル名が格納されているため、今回のような使い方をする場合は必ず../が必要なようです。
ファイル名が/usr/a.rbとして、/usr/libのパスを取得したい場合、実行しているディレクトリの直下にlibがあるからと、File.expand_path("lib","/usr/a.rb")としてしまうと、/usr/a.rb/libが返ってくるようです。
なのでFile.expand_path("../lib","/usr/a.rb")としないと、/usr/libが返ってこないようです。
__FILE__がファイル名ということを忘れずに使わないといけないです。
require
これはrbファイルをロードする命令です。テストコード書くときは、テスト対象のソースを読み込む必要があるのでよく使います。しかし少し調べてみると、loadという似た命令もあるようです。
違いは、requireは1度読みこんだら次は同じrequireが出てきても読み飛ばすそうですが、loadはその都度読み込むそうです。またrequireはrbファイルなら拡張子を省略できますが、loadは省略できないようです。
ここで先程指定したlibにある、ruboty.rbファイルをロードしていることになります。
Ruboty::CommandBuilder.new(ARGV).build.call
最後の一行は、Ruboty::はモジュール名の指定、CommandBuilderがクラス、newで初期化処理、ARGVは引数が格納されている変数、buildとcallはメソッドです。
ここは理解しやすいです。
次は、ruboty.rbの中身を見ていくと上記のモジュールやクラスが出てくるのでしょう。
というわけで、初回は数行のプログラムにもかかわらず知らないことがたくさんでした。次回はruboty.rbのソースを読んでいきたいと思います。