Ruby で掲示板の CGI を作る

April 21, 2008category: Ruby 

サーバサイドのプログラミング能力が貧弱なので、勉強の第一歩として掲示板を作ってみた。ついでに Ruby も覚えてしまおうということで、Ruby で。

要件

  • 名前と本文を投稿できる。
  • Ruby で動く。
  • データベースに MySQL を使う。
  • ビューに ERB を使う。

mod_ruby を入れる

まずは Ruby を CGI で動かすために mod_ruby を入れる (参考)。

MySQL のドライバを入れる

先日入れた

データベースを作る

次にデータベースを作る。フィールドは id、名前、本文、日付の 4 つ。

CREATE DATABASE rubybbs;
GRANT ALL ON rubybbs.* to hogehoge IDENTIFIED BY 'hogefoobar';
USE rubybbs;
CREATE TABLE posts (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(20) NOT NULL,
  date DATETIME NOT NULL,
  body TEXT NOT NULL
);

プログラム本体を書く

次にプログラム本体を書く。

prepare statement と html_escape で、ある程度のインジェクションを回避できるようだ。
また、ERB に外部ファイルを使うときは untaint しないと、eval のセキュリティエラーになる。

#!/usr/bin/ruby

require 'rubygems'
require 'cgi'
require 'mysql'
require 'erb'

#config
DB_HOST = "localhost"
DB_USER = "hogehoge"
DB_PASSWORD = "hogefoobar"
TEMPLATE_FILE = "template.rhtml"
NAME_MAX_CHARS = 20
BODY_MAX_CHARS = 100

cgi = CGI.new
puts cgi.header({"content-type" => "text/html", "charset" => "utf-8"})

db = Mysql::new(DB_HOST, DB_USER, DB_PASSWORD, "rubybbs")
db.query("set character set utf8")

#add
begin
  if (!cgi["name"].strip.empty? && !cgi["body"].strip.empty? && cgi["name"].length < NAME_MAX_CHARS && cgi["body"].length < BODY_MAX_CHARS)
    statement = db.prepare("INSERT INTO posts (name, body, date) VALUES (?, ?, ?)")
    statement.execute(cgi["name"], cgi["body"], Time.now)
  end
rescue
  statement.close
  db.close
  puts "error"
  exit
end

#fetch
begin
  statement = db.prepare("select name, body, date from posts")
  statement.execute
  posts = []
  statement.each do |col|
    posts << {"name" => ERB::Util.html_escape(col[0]),
              "body" => ERB::Util.html_escape(col[1]).gsub(/¥n/, "<br>"),
              "date" => ERB::Util.html_escape(col[2])}
  end
  posts.reverse!
rescue
  statement.close
  db.close
  puts "error"
  exit
end

#render
begin
  puts ERB.new(File.read(TEMPLATE_FILE).untaint, 1).result(binding)
  rescue
    puts "error"
    exit
end

#end
statement.close
db.close

ビューのテンプレートを書く

最後にビュー の rhtml を書く。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta http-equiv="content-language" content="ja">
    <meta http-equiv="content-style-type" content="text/css">
    <title>RubyBBS</title>
    <style type="text/css">
      div.item {
        margin-bottom: 1em;
        background-color: #eee;
      }

      div.item p {
        margin: 0;
      }

      div.item p.name {
        font-size: 1.5em;
      }

      div.item p.body {
        font-size: 2em;
      }
    </style>
  </head>
  <body>
    <h1>RubyBBS</h1>
    <form method="post" action="rubybbs.rb">
      <p>name:<br><input type="text" name="name"></p>
      <p>body:<br><textarea name="body" rows="2" cols="40"></textarea></p>
      <p><input type="submit" value="submit"></p>
    </form>
    <% posts.each do |item| %>
    <div class="item">
      <p class="name"><%= item["name"] %></p>
      <p class="date"><%= item["date"] %></p>
      <p class="body"><%= item["body"] %> </p>
    </div>
    <% end %>
  </body>
</html>

課題

とりあえず動くものはできたが、公開サーバで動かせるレベルではない。
気がついた課題は、

  • 全体的にコードが汚い。無駄が多い。
  • バリデートが甘い。get で投稿できてしまう。
  • 設定ファイルを作るべき。
  • テンプレートファイルは Apache が読めないようにすべき。

とりあえずこんなところ。

comments (0)このエントリーを含むはてなブックマークはてなブックマーク - Ruby で掲示板の CGI を作る

comments