Home / 別館 Home / 楽屋裏 / 2002

楽屋裏から 2002年分


目次


過去の楽屋裏
 2001年 

2002.01.09 明けましておめでとうございました

 明けましておめでとうございました。本年もよろしくお願いいたします。


目次

2002.01.27 悪い癖

 また悪い癖が始まったと言われつつ、新しいパソコンが欲しくなってきました。しかも、またもやノート型。はたして僕は何台ノート型パソコンを持てば気がすむのでしょうか。でも、ちょっとだけ言い訳すると、以前メインで使っていたLet'sNoteは知っている人に譲りました。
 ともあれ、とりあえず自分の希望を整理すると、こんな感じです。

 以上の条件を満たすパソコンをこれから探してきます。お金のことは見つかってから考えよう(そんなんで、いいのか)。

 それはそうと、Rubyの実験を始める。まずは手始めに、『Rubyを256倍使うための本 網道編』を教科書にする。

 最初のものは、こんな感じ。どうも、Xreaでは、.rb ではうまく動いてくれない。.cgiにすると、問題なく動くのだけど……。設定が悪いのだろうか? .htaccess の設定はこんな感じ

【.htaccess の設定】
AddType cgi-script .rb
AddType application/x-httpd-eruby .rhtml
Action application/x-httpd-eruby /usr/local/bin/eruby

目次

2002.01.28 引き続き Ruby の勉強

 引き続き、RubyをCGIとして使う勉強を。

 まずは自分の環境を知るために、こんなのを試してみる。とりあえず、僕のローカル環境ではうまく動作した。サーバー上ではどうだろう(注1)。

 ちなみにこのテストは、環境を知る目的+XreaでeRubyが動くかも確かめています。


【注記】
  1. これを書いているときは、まだサーバーにアップしていません。

目次

2002.01.29 案の定うまく動かず

 昨日、Xreaの環境を調べるために、eRuby を使った実験をしたのだけど、案の定、うまく動いてくれなかった。ローカル環境ではうまく動いたので、サーバー上での設定が悪いのだろう。

 というわけで、eRuby については、Xreaのサポートにたずねるとして、とりあえず普通に Ruby で書くことにする。

 ちなみに、eRuby バージョンはこんな感じ。

eRuby 版
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-2022-JP">
<TITLE lang="ja">environment variables</TITLE>
</HEAD>
<BODY>
<H1>環境変数を表示</H1>
<DL>
<% ENV.each do | name, value | %>
<DT><%= name %></DT> <DD><%= value %></DD>
<% end %>
</DL>
</BODY>
</HTML>

 いろいろと調べた結果、どうやら Xreaには eruby がインストールされていないのじゃないかという結論になった(でも、まだ確信はないのだけど)。

 うーん、どうしよう。eruby を僕のディレクトリにインストールするなんて技術はないし……。かと言って、eRuby を諦めるのもちょっと……。


目次

2002.01.30 「あれどこ」おかげさまで

 おかげさまで、「あれどこ」をVectorで公開してから、500人の方にダウンロードしてもらいました。と言っても、僕のサイトからダウンロードしていただいた方は、カウントしていないので、それも含めると、もうちょっといくのかもしれません。いずれにせよ、本当にありがとうございます。


目次

2002.02.10 掲示板が消える

 Xreaの不具合で、掲示板の書き込みが消えてしまいました。結構、ショック大きいです。

 と言うのも、他のコンテンツは、(ある意味当然ながら)自分のPC上にデータがあるので、復旧はそれほど難しくないのですけれど、掲示板のデータは、サーバー上にしかないわけです。はっきり言って、お手上げ。今回のような事故はそれほど頻繁に起こらないと考えたいのですが、掲示板の書き込みをバックアップする方法も検討しておいた方がいいかも。他の人はどうしているんだろう。

 そうそう、InterWomanの2月の特集で、僕のサイトを取り上げていただきました。今月は、月末発売の『J-skyしようよ』でも紹介してもらう予定になっています。ありがたいこってす。


目次

2002.02.14 バタバタしています

 先週から今週にかけて、なぜかバタバタしています。なぜバタバタしているのか、自分でも理由が分かりません。気が付いたら今日は金曜日かという日々だったりします。30歳、もうちょっと落ち着いて生活しようと思います。

 それはともかくとして、掲示板のデータが消えた問題、なんとか解決しました。データをバックアップしてくれていたXreaに感謝。ただ、僕の掲示板はたま〜に書き込みがある程度なので、これでよかったけれど、活発な掲示板だとこうはいかなかったのでしょうね。

 ともあれ、このサーバーの環境を調べる実験、以前見事に失敗していましたが、再度チャレンジ。Rubyのライブラリを調べていたら、CGIライブラリの中にちゃんとサンプルが書いてありました。今度はそれを使って試してみます。


目次

2002.02.17 Xreaの環境

 と言うわけで、予告通り、Xreaの環境を調べる実験をしました。使ったCGIは下記の通りです。


#! /usr/local/bin/ruby
# サーバーの環境を取得する
require "cgi"
cgi = CGI.new("html4")  # add HTML generation methods
cgi.out() do
  cgi.html() do
    cgi.head{ cgi.title{"TITLE"} } +
    cgi.body() do
      cgi.pre() do
        CGI::escapeHTML(
          ENV.collect() do |key, value|
            key + " --> " + value + "¥n"
          end.join("")
        )
      end
    end
  end
end

 その結果は、下記の通り。


PATH --> /usr/local/bin:/usr/bin:/bin
DOCUMENT_ROOT --> /virtual/tomikura/public_html
HTTP_ACCEPT --> */*
HTTP_ACCEPT_ENCODING --> gzip, deflate
HTTP_ACCEPT_LANGUAGE --> ja
HTTP_CONNECTION --> Keep-Alive
HTTP_HOST --> tomikura.s2.xrea.com
HTTP_REFERER --> http://tomikura.s2.xrea.com/mkweb/index.html
SCRIPT_FILENAME --> /virtual/tomikura/public_html/cgi-bin/env.cgi
SERVER_ADDR --> 61.206.38.202
SERVER_ADMIN --> admin@s2.xrea.com
SERVER_NAME --> tomikura.s2.xrea.com
SERVER_PORT --> 80
SERVER_SOFTWARE --> Apache/1.3.22 (Unix) mod_layout/3.0.3 mod_gzip/1.3.19.1a
GATEWAY_INTERFACE --> CGI/1.1
SERVER_PROTOCOL --> INCLUDED
QUERY_STRING --> 
REQUEST_URI --> /cgi-bin/env.cgi
SCRIPT_NAME --> /cgi-bin/env.cgi

目次

2002.03.21 落語検索システム

 落語の検索システムと言えば、落語検索エンジン「ご隠居」が有名です。実際非常に便利で、僕も時々利用させてもらっているのですが、僕のサイトのお題も200題を超えた頃から、検索できた方が便利という声をいくつかもらうようになりました。XreaではCGIが使えるので、現在、検索用のCGIを作っています。

 先週末、ローカルでのテストも無事終わり、いよいよサーバーで公開しようと思ったのですが、どういうわけか上手く動いてくれません。うーん、どうしてだろう。特に変わったことしているわけではないのだけど……。eRubyを使っているのが悪いのかなぁ。

 ちょっとeRuby(正確には、erblライブラリ)を使った実験をしてみたところ、どうも問題は検索用のCGI側ではなく、erblのrequireの仕方に問題がありそう。気になる部分を直して、サーバーで実験してみよう。

 などと呑気なことを考えていたら、掲示板そのものも同じ症状になっていることが発覚。うわー、なぜだ! 3月14日までは正常に動いていたので、多分、今回ごちょごちょやっていたときに、.htaccess の設定か、パーミッションの設定を間違えるような操作をしてしまったのだろう。困った。

 取り急ぎ、.htaccess の設定を下記の通り記述する。

Addtype cgi-script .cgi

目次

2002.03.24 落語検索システム続き

 先日の問題、何とか解決。不具合の原因は、すべて eRuby で出力しようとしていたこと。最初のおまじないについては、大人しく print で出すことにすると、うまく動いた。

 と言うわけで、後はコツコツとデータの入力。


目次

2002.04.06 落語検索システムのソース

 反面教師になるかもしれないので、先日作った落語検索CGIのソースコードを掲載しておこう。正直恥ずかしいけれど、今の僕はこのレベルということで。


#! /usr/local/bin/ruby
# 落語検索(SearchRakugo)
# FileName: rakugosearch.cgi
# Author: Masaya Tomikura (vzx01036@nifty.ne.jp)

=begin
=機能
 フォームから取得した検索語とデータファイルを比較し、マッチした行の「お題」と「URL」を取得する。
 結果は、eRuby で整形して出力する。
=データファイルの書式
お題(title):URL(url):登場人物(person):落ち(punch_line):キーワード(keyword)
=検索対象
お題、登場人物、落ち、キーワード
=【履歴】
 2002.03.10 : Ver.1.00
 2002.03.28 : Ver.1.10
    正規化表現をまとめる。
    文字コードをEUCにセットする。
=end

require 'cgi'
require 'erbl.rb'
require 'kconv'

class SearchRakugo
  ### 初期化 ###
  def initialize
    cgi = CGI.new('html4')
    @result = []
    
    @title = setCode(cgi['title'][0])
    @person = setCode(cgi['person'][0])
    @punch_line = setCode(cgi['punch_line'][0])
    @keyword = setCode(cgi['keyword'][0])
  end
  
  ### 文字コードをEUCに変換 ###
  def setCode(word)
    if word == '' then word = ''
    else word = Kconv.toeuc(word)
    end
  end
  
  ### 検索ルーチン ###
  def search
    db_name = "rakugo.dat"  # データファイルの指定
    i = 0
    
    # 検索語を正規表現に変換
    stitle = setReg(@title)
    sperson = setReg(@person)
    spunch = setReg(@punch_line)
    skey = setReg(@keyword)
    
    # 検索語にマッチする行からお題とURLを取得
    File.foreach(db_name) do |line|
      title, url, person, punch_line, keyword = line.split(/:/)
      if (stitle =‾ title && sperson =‾ person && spunch =‾ punch_line && skey =‾ keyword)
        @result[i] = line
        @result[i] = []
        @result[i] = url, title
        i = i + 1
      end
    end
  end
  
  ### 検索結果の表示 ###
  def show
    result_file = File::readlines("result.rhtml").join
    print "Content-Type: text/html; charset=EUC-JP¥n¥n"
    print ERbLight::new(result_file).result(binding)
  end
  
  ### 検索語の正規表現化 ###
  def setReg(word)
    if word == nil then word = //
    else word = Regexp.new(word)
    end
  end
end

##### ここからがメイン #####
rakugo = SearchRakugo.new
rakugo.search
rakugo.show

目次

2002.05.06 備忘録に検索機能?

 備忘録のページに検索機能を付けようか? さすがに200超えると、テキストだけとはいえ表示までに時間がかかるし……。

 欲しい機能としては、分野毎に表示する機能と、キーワード検索ができれば充分なので、なんとかなるかも。


目次

2002.06.10 備忘録に検索機能

 備忘録のページに検索機能を付ける計画、とりあえずインタフェースとアプリケーション部分のプロトタイプができあがる。後はデータの変換。こちらはコツコツするしかないか。


目次

2002.06.17 とりあえず完成

 5月6日に思い立った備忘録に検索機能を付ける件、サーバー上でのテストに成功する。今回作ったスクリプトはこんな感じです。


#! /usr/local/bin/ruby
=begin
 備忘録検索システム
 Author : Masaya Tomikura (vzx01036@nifty.ne.jp)
 ver.1.00 : 2002.06.17
=機能
 フォームから取得した検索語とデータファイルを比較し、マッチした項目を表示する。
 また、フォームからではなく、リンクからも指定できる。(現状、未実装)
=データ形式
No◆カテゴリー◆本文◆発言者◆出典◆日付

=end

require 'cgi'
require 'kconv'
require 'erbl'

##### 検索語クラス #####
=begin
このクラスでは、下記のことを行う。
*文字コードをEUCに変換する

なお、注意点として、引数はハッシュを前提とする。具体的には、cgi.paramsから取得する
=end

class Word
  attr_reader :form
  
  def initialize(hash)
    @form = hash
    
    set_euc()
  end
  
  private
  
  ### EUCに設定 ###
  def set_euc
    @form.each_key {|key|
      # cgiのフォームに入力がない場合は「""」に設定する
      @form[key] = "" if @form[key].first == nil
      @form[key] = Kconv::toeuc(@form[key].first)
    }
  end
end


##### 検索クラス #####
=begin
 このクラスでは、下記のことを行う。
*ファイルからデータを取得する。
*引数として与えられたキーワードを正規化した上で検索する。
*結果は、eEubyを使って出力する。
=end

class Search
  def initialize(word)
    @target = word
    @result = []
    
    search()
    show()
  end
  
  private

  ### 検索 ###
  def search
    db_name ="oneline.dat"
    search_word = {}
    i = 0
    
    # キーワードを正規化する
    @target.each_key {|key|
      # @target そのものではなく、正規化したキーワードは search_word[] とする
      search_word[key] = Regexp.new(@target[key])
    }
    
    # 実際に検索する
    File.foreach(db_name) do |line|
      line.chop!
      no, category, oneline, person, source, date = line.split("◆")
      if (  search_word['categoly'] =‾ category &&
            search_word["word"] =‾ oneline &&
            (search_word['person'] =‾ person || search_word['person'] =‾ source))
        @result[i] = line
        @result[i] = []
        @result[i] = no, oneline, person, source, date
        i = i + 1
      end
    end
  end

  # 結果を出力する
  def show
    result_file = File::readlines("result.rhtml").join
    print "Content-Type: text/html; charset=EUC-JP¥n¥n"
    print ERbLight::new(result_file).result(binding)
  end
end

##### ここからがメイン処理 #####
cgi = CGI.new('html4.0')
word = Word.new(cgi.params)
Search.new(word.form)

 本当は、データの区切りを「◆」なんて特殊な文字を使わずに、「,」の方がいいのだろうけれど、ちょっと面倒くさいことになりそうなので、手抜きしています。

 出力するための rhtmlファイルは、こんな感じです(こちらは必要な部分だけ)。


<!-- ユーザの指定した語句を表示 -->
<%
  if @target['categoly'] == "" then
    @target['categoly'] = "なし"
  end
  if @target['word'] == "" then
    @target['word'] = "なし"
  end
  if @target['person'] == "" then
    @target['person'] = "なし"
  end
  hit = @result.size

%>
<P class="result">カテゴリー<STRONG>「<%= @target["categoly"] %>」</STRONG>、
キーワード<STRONG>「<%= @target['word'] %>」</STRONG>、
人物<STRONG>「<%= @target["person"] %>」</STRONG>
で検索した結果、<STRONG><%= hit %>件</STRONG>見つかりました。</P>

<HR>
<!-- 検索結果を表示 -->
<% if @result.empty? then %>
<P> お探しのものは見つかりませんでした……。</P>
<% else %>
  <% @result.each do |result| %>
  <P><STRONG>#<%= result[0] %></STRONG> <%= result[1] %><BR>
  <SMALL>【<%= result[2] %>】 (<%= result[3] %>) (<%= result[4] %>)</SMALL></P>
  <% end %>
<% end %>

目次

2002.07.14 韓国からのメール

 しばらく前から、なぜか韓国からのダイレクトメールが届くようになりました。最近では毎日10通くらいのペースで届いています。多分ダイレクトメールだと思うのですが、僕の環境ではそもそもハングル文字を表示できないので、何が書いてあるのかさっぱり分かりません。

 AirHでつなぎ放題環境なので、特に神経質になっているわけではないのですが、でもそろそろ煩わしくなっているのも確かです。せめて英語で送ってくれれば……。


目次

2002.08.14 掲示板

 今、僕のサイトで使っている浜ちゃんの浜ちゃん的心の掲示板スクリプト、使いやすいのだけど、微妙な点で違和感があります。これ、どうにかならないかなぁと最近感じています。

 具体的には、こんなところがちょっと……な点です。

  • 書き込み部分のレイアウトのカスタマイズが、CSSレベルでしかできない。
  • 書き込み時のメールがうまく機能していない。
  • 投稿フォームの要素を自由にカスタマイズできない。

 細かな点では、投稿者の IPアドレスを書きだしているとか、「さん」を自動的につけてしまうという問題もあります。

 僕が Perl を自由に読み書きできれば、簡単に直せる範囲なのかもしれないのですが、残念ながら、Perl はよく分かりません。勉強もかねて、Ruby で自作してみようか。


目次

2002.08.15 引き続き掲示板 欲しい機能(大まかに)

 と言うわけで、引き続き掲示板について。

 僕が必要だと思う機能は、こんな感じです。

  1. 1つのスクリプトで、複数の掲示板を運営できること。
    1. それぞれの掲示板の外見を変更できること。
    2. それぞれの掲示板の入力項目、表示項目を変更できること。
  2. 書き込みがあったときにメールで通知する機能。
  3. 元記事に対して自動的にリンクが張られること。

 まずはこういうことができそうな既存の掲示板CGIを探してみよう。


目次

2002.08.27 引き続き掲示板(ユースケース)

 引き続き、Rubyで書かれた掲示板を探しつつ、勉強もかねて自分で掲示板が作れないか考えています。

 とりあえず、非常におおざっぱなユースケースを書いてみよう。

ユースケース
 掲示板ユースケース
ゴール
 HTMLを書き出す
概要
 掲示板は、「新規投稿」もしくは「返信」ボタンが押されると、投稿用の画面を出す。「返信」ボタンが押された場合は、元記事のIDを取得する。投稿画面で「投稿」ボタンが押されると、ユーザによって記入されたHTML要素を無効化した上で、URLについてはリンクを張り、HTMLとして書き出す。
シナリオ
(1) ユーザによる書き込み
(2-1)「新規投稿」ボタンが押された場合
(2-2)「返信」ボタンが押された場合
 元記事のIDを取得する
(3) 書き込み用画面を表示する
(4) 「投稿」ボタンが押される
(5) 書き込み内容を取得する
(6) 書き込み内容から HTML タグを無効化する
(7) 書き込み内容の URL と思われる部分にリンクを張る
(8) 掲示板の最新記事 ID を取得する
(9-1) 過去ログを作成する必要がある場合
 現在の index ファイルを過去ログに移行する
 新しく index ファイルを作成する
(9-2) 過去ログを作成する必要がない場合
 現在の index ファイルに新しい書き込みを追加する
(10) index ファイルを再表示する

目次

2002.09.02 掲示板(クラス候補)

 クラス候補になりそうなのは、「掲示板」と「投稿記事」くらいなのかなぁ。とりあえず、掲示板のクラスについて考えてみよう。

# 掲示板クラス
require 'erb/erbl'

class Board
  def initialize( board_url )
    @board_url = board_url	# 書出し先の位置を把握
  end
  
  def post( reply_no = "" )
    # 投稿画面を出力する
    # 出力には ERuby を使用
  end
  
  def write( article = "" )
    # 投稿された記事を HTML に書き出す
    # 出力には ERuby を使用
  end
  
  def make_log
    # 一定数の書き込みがあった場合、過去ログを作成する
  end
end

 HTMLファイルを作成するときには、ファイルのロック機能が必要になる。あと、過去ログの作成はプライベートメソッドにした方がよさそう。


目次

2002.09.11 とりあえずテストスクリプト

 とりあえず、RubyUnitを使って、掲示板クラスのテストスクリプトを作り始める。初期化部分のテストスクリプトは、こんな感じ。

require 'runit/testcase'
require 'runit/cui/testrunner'
require 'board'

class TestBoard < RUNIT::TestCase
  ### 初期化のテスト ###
  def test_initialize
    board = Board.new("test_bbs")
    assert_instance_of(Board, board)
  end
end

if $0 == __FILE__
  if ARGV.size == 0
    suite = TestBoard.suite
  else
    suite = RUNIT::TestSuite.new
    ARGV.each do |testmethod|
      suite.add_test(TestBoard.new(testmethod))
    end
  end
  RUNIT::CUI::TestRunner.run(suite)
end

目次

2002.09.15 じゃんけんするJavaScript不具合

 「がらくた箱」で公開していた「じゃんけんするJavaScript」に不具合。クリアボタンを押しても、表示上は「0勝0敗0分」になっているにもかかわらず、内部的にはクリアになっていなかった。

 これ、すごく単純なミスで、クリアボタンに対応する関数内で、

function cls()
{
  var win = 0;
  var lose = 0;
  var even = 0;
}

と再び変数宣言をしていたというポカミス。恥ずかし〜! しかも、1年間も気付かずに放置されっぱなし。うひゃ〜。指摘してくださったオオカミさんに、感謝、感謝!

 ともあれ、もう一つの課題、Mozilla1.0 及び Wazilla1.0で、フォーム内に情報を表示することについても対応したいのだけど、メインで使っている Libretto には IE 以外のブラウザを入れていないので、検証に時間がかかりそう。Linux 上で作業した方がいいかも。


目次

2002.09.19 新規書き込みと返信について

 再び掲示板について。

 僕が Libretto ff という小さなディスプレイで作業をしているからなのでしょうけれど、書き込み画面は別ウィンドウで立ち上がってくれた方が、何かと好都合です。あと、返信の場合は、自動的に元記事にリンクを張ってくれればいいなと思います(今の浜ちゃんの浜ちゃん的心の掲示板スクリプトでは、投稿者が元記事の番号を入力する仕組みになっています)。

 入力画面そのものは、eRuby を使うことにして、とりあえず 掲示板クラスの役割としては、

  1. 入力項目は eRuby 側で設定する。
  2. 返信の場合は元記事番号を自動的に設定する。

こんなところ。返信の場合であれば元記事の番号を受け取って、出力画面を作成すればいいか。新規投稿の場合は、元記事の設定なしで出力画面を返すというのが post メソッドの働きにする。

 と言うわけで、投稿画面を出すメソッドのテストスクリプトはこんな感じに。

  ##### post メソッドのテスト #####
  def test_post
    reply1 = "1"
    reply_nil = nil
    post_html = File::readlines("test_bbs/post.html").join
    board = Board.new("test_bbs")
    
    # reply があった場合
    reply_num = "1"
    post_interface = ERbLight::new(post_html).result(binding)
    assert_equal(post_interface, board.post(reply1))
    
    # 新規投稿の場合
    reply_num = ""
    post_interface = ERbLight::new(post_html).result(binding)
    assert_equal(post_interface, board.post(reply_nil))
  end

 実際のスクリプトは、こんな感じ。

  ##### 投稿画面の提供 #####
  def post( reply_num )
    reply_num = "" if reply_num == nil
    post_html = File::readlines(File::join(@board_url, "post.html")).join
    return ERbLight::new(post_html).result(binding)
  end

目次

2002.10.05 掲示板の書き込み部分

 ここしばらく放置プレイ状態だった掲示板について、この週末はちょっと時間をとれそうなので続きをば。

 Board クラスとしては、投稿フォームからの入力内容を元に新しく index ファイルを再構築する実装が必要になるのだろうけれど、Board クラスを呼び出す側にしてみたら、どんな風に書き込まれたかなんてことは、知ったこっちゃないわけで、とにかく書き込み後の index ファイルを表示できればいいわけなんだろうから、具体的には書き込み後の掲示板の URI を取得できればいいのではないかと思う。

 と言うわけで、Board クラスの write メソッドの骨格はこんな感じになるのかなぁ。

  ##### 記事の書き込み #####
  def write ( article )
    # 何らかの方法で index ファイルを作成
    return File::join( @board_url, "index.html" )
  end

 でも、テストとしては、正常に(というか意図通りに)書き込まれたかを確かめたいわけなので、そのためのテストコードはどう書けばいいのだろう?


目次

2002.10.12 掲示板の書き込み部分(続き)

 掲示板の書き込み部分について、引き続き。

 最終的には、書き込み後の index ファイルの URI を返すとしても、index.html への書き込みそのものは掲示板クラスのお仕事。単純に考えれば、index.html 内に特定の目印を付与しておいて、その目印を見付けたら、そこに新しい書き込み部分を書きだして新しく index.html を生成する方法にするのが楽そう。

 テストコードは、すごくずぼらな気がするけれど、こんな感じにしてみる。

  ##### 記事書き込みの確認 #####
    def test_write
      article = {"title" => "test title",
                 "name" => "hogehoge",
                 "body" => "これは書き込みのテストです"}
      File::copy("test_bbs/base_index.html", "test_bbs/index.html")
      board = Board.new("test_bbs")
      board.write(article)
      test_new_index = File::readlines("test_bbs/test_new_index.html").join
      new_index = File::readlines("test_bbs/index.html").join
      
      assert_equal(test_new_index, new_index)
    end

 実際のコードはこんな感じ。

  def write( article = "" )
    num = File::readlines(File::join(@board_url, "id")).join.to_i + 1
    template_file = File::readlines(File::join(@board_url, "template.rhtml")).join
    new_article = ERbLight::new(template_file).result(binding)
    index_file = File::join(@board_url, "index.html")
    
    if num % @max_num == 1 && num != 1
      # backup ファイルの作成処理
    else
      backup_file = File::join(@board_url, "index.bak")
      File::rename(index_file, backup_file)
      p_write(new_article, backup_file)
    end
    return index_file
  end
  
  ## 最終的には private メソッド化する 
  def p_write( new_article, base_file )
    File::open(File::join(@board_url, "index.html"), "w"){|index_file|
      File::open(base_file, "r"){|file|
        while line = file.gets
          if line =‾ //
            index_file.write(new_article)
          else
            index_file.write(line)
          end
        end
      }
    }
  end

 とりあえずこれでテストが通ったので、次はバックアップファイルの作成処理に取りかかろう。


目次

2002.10.29 Boardクラスアルファ版

 例外処理は一切なしの状態ですけど、とりあえず Boardクラスの基本的な機能は完成。スナップショットは、こんな感じです。

#! /usr/local/bin/ruby

require 'erb/erbl'

class Board
  def initialize( board_url )
    base_url = "./"
    @board_url = base_url + board_url
    
    # 指定されたディレクトリが存在しない場合の処理
    
    # ここから先は最終的に設定ファイルに移行
    @max_num = 20
    @board_file = "index.html"
  end
  
  ##### 投稿画面の提供 #####
  def post( reply_num )
    reply_num = "" if reply_num == nil
    post_html = File::readlines(File::join(@board_url, "post.html")).join
    return ERbLight::new(post_html).result(binding)
  end
  
  ##### 書き込み #####
  def write( article = "" )
    num = p_number()
    template_file = File::readlines(File::join(@board_url, "template.rhtml")).join
    new_article = ERbLight::new(template_file).result(binding)
    index_file = File::join(@board_url, @board_file)
    
    ### 過去ログの作成判断 ###
    if num % @max_num == 1 && num != 1
      backup_file = p_make_log(num)
    else
      backup_file = File::join(@board_url, "index.bak")
      File::rename(index_file, backup_file)
    end
    
    p_write(new_article, backup_file)
    return index_file
  end
  
  ##### 実際の書き込み #####
  def p_write( new_article, base_file )
    File::open(File::join(@board_url, @board_file), "w"){|index_file|
      File::open(base_file, "r"){|file|
        while line = file.gets
          if line =‾ //
            index_file.write(new_article)
          else
            index_file.write(line)
          end
        end
      }
    }
  end
  
  ##### ログの作成 #####
  def p_make_log( num )
    file_num = (num / @max_num).truncate
    log_file = file_num.to_s + ".html"
    index_file = File::join(@board_url, @board_file)
    
    File::rename(index_file, File::join(@board_url, log_file))
    
    body_template = File::readlines(File::join(@board_url, "body_template.rhtml")).join
    backup_file = File::join(@board_url, "index.bak")
    File::open(backup_file, "w"){|file|
      file.write(body_template)
    }
    return backup_file
  end
  
  ##### 記事 id の管理 #####
  def p_number
    # idファイルが存在しない場合の処理
    id_file = File::join(@board_url, "id")
    num = File::readlines(id_file).join.to_i + 1
    File::open(id_file, "w"){|file|
      file.write(num)
    }
    return num
  end
end

 まだまだ、怪しげな部分はたくさんあるし(危険な香もするし)、それ以前に、ファイルロックに関する処理と、各種の例外処理をくわえていかなければいけないのだろうけれど、とりあえずプロトタイプは出来たと自分を納得させ、これからしばらくは入力されたフォームデータに対する処理について考えていこう。


目次

2002.11.05 フォームからの投稿内容を処理するクラス

 とりあえず、Boardクラスの作業はこれくらいにして、フォームの内容を取得して、それに対する処理を行うクラスについて考えていこう。

 繰り返しになるけれど、やりたいことはこんなこと。

  • フォームに記入された内容を取得する。
  • 文字コードを EUC に変更する。
  • HTML のタグを外す。
  • URLやメールアドレスに対してリンクを張る。

 こんなところかなぁ。


目次

2002.11.11 Articleクラス

 CGI クラスで取得したフォームからの入力項目は、{'key' => ['value1', 'value2'...]}みたいな感じで格納されるので、value の最初の値だけを取り出すことにして、こんな感じになるのかなぁ、

class Article
  def initialize( cgi_params )
    @params = {}
    @params.default = ""
    @params = cgi_params.first
  end
end

 テストスクリプトはこんな感じ。

class TestArticle < RUNIT::TestCase
  def test_initialize
    cgi_params = {
      "test1" => ["test_1", "test_2"],
      "test2" => ["test_2"],
      "test3" => [nil]
    }
    article = Article.new(cgi_params)
    assert_instance_of(Article, article)
    assert_equal("test_1", article.params["test1"])
    assert_equal("test_2", article.params["test2"])
    assert_equal("", article.params["test3"])
  end
end

目次

2002.11.12 Articleクラスの手直し

 昨日思いついた記述だと、テストを通ってくれない。と言うわけで手直し。

class Article
  attr_reader :params
  
  def initialize( cgi_params )
    @params = Hash.new()
    @params.default = ""
    cgi_params.each_key{|key|
      if cgi_params[key].first == nil
        @params[key] = ""
      else
        @params[key] = cgi_params[key].first
      end
    }
  end
end

 ついでに、[] で params の値を取り出せるようにする。

  def []( *args )
    @params[*args]
  end

 これにあわせてテストスクリプト部分も書き直す。

  def test_initialize
    (省略)
    assert_equal("test_1", article["test1"])
    assert_equal("test_2", article["test2"])
    assert_equal("", article["test3"])
    assert_equal("", article["none_key"])
  end

 これが通ったので、機能部分について。

 文字コードの変換で用意しておきたいのは、EUC と JIS なので、それを実装しよう。Kconv 使うのが楽かも。例によって、何も考えずに書いたスクリプトは、こんな感じ。

  def toeuc
    @params.each_key{|key|
      @params[key].toeuc
    }
  end
  
  def tojis
    @params.each_key{|key|
      @params[key].tojis
    }
  end
  
  def toeuc!
    @params.each_key{|key|
      @params[key] = @params[key].toeuc
    }
  end
  
  def tojis!
    @params.each_key{|key|
      @params[key] = @params[key].tojis
    }
  end

目次

2002.11.16 Articleのメソッド

 今日は時間があるので、Articleのメソッドを書いていこう。

 HTMLタグを外すメソッドと、リンクを設定するメソッドを書く。ソースコードをここに記載しておこうと思ったのだけど、HTMLの要素をうまく表示することが出来なかったので、とりあえず、スナップショットを別ファイルでおいておきます。

 改行コードを見付けたら、<BR> を付加するメソッドを書こうと思ったのだけど、ちょっと詰まる。

  def set_br
    self.gsub(/¥n/, "<BR>¥n;")
  end

 こんな感じで記述できそうなのだけど……、これを、article["test1"].set_br みたいな使い方をしたいけど、これ、Article クラスのメソッドにしてしまうと、あまり面白くないかも。String クラスを拡張した方がいいのかなぁ。


目次

2002.11.22 再びBoardクラス

 とりあえず、Article クラス側でやりたいことはできあがったような気がしてきたので、再びBoardクラスに手を入れる。

 残る作業としては、

  • ファイルのロック機能
  • 例外処理
  • リプライの場合に元記事にリンクを張る

 こんなところかなぁ。

 元記事へのリンクについては、正直 Board クラスの役割にすべきかどうか迷っているのだけど(と言うか、eRuby 側で処理した方がいいような)、とりあえずは Board クラスのメソッドにしておく。

  def reply( re_num, str )
    if re_num == ""
      link_article = ""
    else
      id_file = File::join(@board_url, "id")
      num = File::readlines(id_file).join.to_i
      file_num = (re_num.to_i / @max_num).truncate + 1
      if file_num == (num / @max_num).truncate + 1
        link_article = '<A href="#' + re_num.to_s + '">' + str + '</A>'
      else
        link_article = '<A href="' + file_num.to_s + '.html#' + re_num.to_s + '">' + str + '</A>'
      end
    end
    return link_article
  end

 自分で書いていて、あまりスマートじゃないような気がしてきたけど……。

 テストコードはこんな感じ。

  def test_reply
    article = {"test1" => "10"}
    File::copy("test_bbs/base_index.html", "test_bbs/index.html")
    make_id_file("25")
    board = Board.new("./test_bbs")
    board.write(article)
    assert_equal('', board.reply("", "元記事"))
    assert_equal('<A href="1.html#10">元記事</A>', board.reply("10", "元記事"))
    assert_equal('<A href="#21">元記事</A>', board.reply("21", "元記事"))
  end


目次

2002.11.25 ファイルのロック

 たとえ1週間に2、3個の書き込みしかないとしても、その2、3個が一度に集中するということは充分考えられるので、ファイルのロック機能は必須です。というわけで、掲示板に実装しなければいけないのですけれど、手抜きして本体のモジュールは、256倍に掲載されているものをそのまま使うことにする。楽だ〜。


目次

2002.12.20 掲示板スクリプト とりあえず一段落

 暇を見つけて、こそこそと作ってきた掲示板スクリプトですが、とりあえずローカルでの稼働試験に成功。と言うわけで、この週末に時間を作れれば、Xreaでの試験運用を始めてみようと思う。

 がらくた箱で公開するかどうかは、まだちょっと微妙。ドキュメントを作成しなければいけないのは勿論だけど、管理ツールとか、テンプレートの例をいくつか作れてからにしようかなぁ。とは言いつつ、バザール方式に乗っ取って、できたらとりあえず公開してしまうというのもありだと思うけれど。

ともあれ、掲示板を作ろうかなと思い立ってから、ここまでこぎ着けるのに、なんだかんだ言いながら4ヶ月経っているわけで、やっぱプログラムを本職にしなくてよかったと思う今日この頃。


目次


とみくら まさや(vzx01036@nifty.ne.jp) $ Date: 2001/09/22 $