以下のプログラムはアクセスカウンタとして動作するものです。
1: #!/usr/bin/env ruby 2: print "Content-Type: text/html\n\n" 3: CFILE="counter.dat" 4: # カウンタの値を読み込む 5: begin 6: fp = open(CFILE, "r") 7: counter = fp.gets.to_i + 1 8: fp.close 9: rescue 10: counter = 1 11: end 12: # カウンタの値を書き込む 13: fp = open(CFILE, "w") 14: fp.print counter 15: fp.close 16: # カウンタの値をHTML形式で表示する 17: print "<HTML><BODY>\n" 18: print "counter=#{counter}\n" 19: print "</BODY></HTML>\n"
このプログラムは、counter.dat というファイルにカウンタの値(整数値)を格納し、 実行されるたびにカウンタの値を1つ増やしています。このプログラムは大まかに4つの処理から成り立っています。
以下は、それぞれの詳細について説明します。
前の例と同様にhttpのヘッダで、html形式であることを標準出力に出力します。
カウンタの値を入れておくファイルcounter.datを読み込みます。 ファイルを読み込むには、まず「ファイルを開く」という操作をします。 ファイルを開くにはopenメソッドを使います。Rubyでopenメソッドを使うやり方は色々とありますが、この場合は、C言語など他の言語に近い使い方をします。
fpはopenメソッドが返す値が入ります。この値はファイルを操作するために後で使うため、fpに代入しておくのです。 ファイル名には、文字列でこれから開くファイル名を指定します。この場合は、2行目で"counter.dat"をCFILEに代入して、そのCFILEを使っています。つまり、6行目では"counter.dat"を開こうとします。"r"とあるのは、readの頭文字で、ファイルを読み込むために開くことを意味します。
ファイルがうまく開けたら、7行目でファイルから一行読み込みます。fp.getsというところに注目してください。getsはキーボード(標準入力)から一行入力するメソッドでした。ファイルの場合は、同じようにfp.getsと書けば、一行読み込むことができるのです。 ただし、標準入力の場合は、「ファイルを開く」という操作が必要ない(最初から開いている)のにたいして、ファイルの場合は読み込む前に必ずファイルを開く操作が必要なところが違います。
一行入力したものは、.to_i で整数値に変換して、さらに1を足したものを変数counterに代入しています。
8行目では、「ファイルを閉じる」という作業をしています。一度開いたファイルは使い終わったら「閉じる」ことが必要です。実はプログラムが終了したら、自動的に閉じてくれるのですが、このプログラムのように再度開くこともあるので、きちんと閉じる習慣をつけてください。8行目が終るとrescue 〜 end を飛ばして13行目に移ります。
なお、ファイルが開けないということがあります。例えば、ファイルが存在しないとファイルは開けません。この場合、ファイルが開けないと、rescue 〜 end の間、つまり10行目が実行されます。つまり、変数counterの値を1にします。これは「例外」という仕組みを使ったものですが、説明は省略します。今の時点では、このようなものと思ってください。
このプログラムでは、counter.dat というファイルにカウンタの値を記録して、 次回にcounter.cgiを読んだ時に使います。つまり、counter.datに書き込まないことにはうまく機能しないのです。
ファイルに書き込むのは、ファイルを読み込む操作に非常に似ています。 13行目でファイルを開きます。読み込みときと違うのは、"r"が"w"になっていることです。 "w"はwriteの頭文字です。つまり、書き込むためにファイルを開きます。 なお、書き込むためのファイルがすでに存在する場合には、その内容を全て消してから書き込みます。この場合、counter.datが存在していても、counter.datの内容は全て消されるのです。
14行目で、ファイルカウンタの値を書きこんでいます。読み込みでgetsを使ったように、ここではprintを使っています。画面(標準出力)に出力するには、printメソッドを使いましたが、ファイルに書きこむ場合は、fp.print とします。 15行目で、ファイルを閉じています。ファイルを閉じるのを忘れないように心がけてください。
ここは、以前に習った通りです。HTML形式で、「counter=カウンタ値」という内容を表示しています。18行目には文字列中に変数counterの値を入れ込んでいますが、 print "counter = ", counter, "\n"としても同じです。
このプログラムには、1つ問題があります。アクセスが集中すると、カウンタの値が1に戻ってしまいます。この問題を解消するには排他制御を行う必要があり、普通はファイルのロックという作業を行います。プログラムがさらに複雑になるので、ここではそこまではやりませんが、実用的なCGIプログラムを作成するには欠かせない事項です。興味のある人は関連する文書を探して勉強してみてください。
以上で、Webページを何回アクセスしたかを示すアクセスカウンタが作成できましたが、 通常アクセスカウンタは、長いHTMLファイルの中に埋め込んで使いたいものです。 その方法にはいろいろとありますが、ここでは、CGIプログラムを呼び出して、 そのプログラムの中から表示したいhtmlファイルを読み込み、指定した場所にアクセスカウンタを埋め込んで表示するようにします。
以下では読み込むファイルを、esample.html とし、そのファイルの中に、 ACCESS_COUNTERという行があれば、それをアクセスカウンタの値に付け替えるようにしています。
#!/usr/bin/env ruby print "Content-Type: text/html\n\n" CFILE="ecounter.dat" HFILE="esample.html" # カウンタの値を読み込む begin fp = open(CFILE, "r") counter = fp.gets.to_i + 1 fp.close rescue counter = 1 end # カウンタの値を書き込む fp = File.open(CFILE, "w") fp.print counter fp.close # HTMLファイルを読み込み、その内容を出力する begin fp = open(HFILE, "r") while s = fp.gets do # ファイルから1行読み込む # もし"ACCESS_COUNTERなら"、カウンタの値に入れ替える if (s.chomp == "ACCESS_COUNTER") then s = "#{counter}\n" end print s # 1行分を標準出力に出力 end fp.close rescue print "<HTML><BODY>File not Found</BODY></HTML>\n" end