Ruby

Rubyは偉大だなあ、と思い始めた。

OCamlでもC#でも、私の好きなプログラミング言語は他にもあるが、Rubyの楽さにはかなわないと思う。

先日、TAをやっているレポートをメールで提出させる授業に必要になって、添付ファイルでプログラムを提出させて添付ファイルを学籍番号で作ったディレクトリに振り分けさせるプログラムを書いた。これをRubyで書いたのだが、死ぬほど楽だったし、すぐ書けた。多分これまでそういうプログラムになっていなかったのは、添付ファイルやメールを扱うプログラムを書くのが大変だったからなんだろうが、その問題はRubyとTMailを使うことで一瞬で解決された。たった70行のプログラムで、すごく楽になれたのだ。

結構感動。

上の話ではないが、こういうプログラムをちゃちゃっと書ける*1かどうかというのは、相当大きな差だよなあ、と思った。

これがそのプログラム。これを.forwardで起動してやればよい。

#!/bin/env ruby
require "tmail"
require "net/smtp"
require "fileutils"

REPORT_DIR = "/home/lecture/05"

def move(f)
  if (File.exists?("#{f}~"))
    move(f+"~")
  end
  FileUtils.mv(f, f+"~")
end

def save(id, fname, body) 
  dir = "#{REPORT_DIR}/#{id}"
  path = "#{dir}/#{fname}"

  if (not File.directory?(dir))
    FileUtils.mkdir(dir)
  end

  if (File.exists?(path))
    move(path)
  end

  File.open(path, "w") { |f|
    f.puts(body)
  }
end

def create_reply(received, reply)
  msg = <<EOM
某授業のレポートを受理しましした。
課題の解答として受理したファイルは、以下の通りです。

#{received.join(", ")}
EOM
  reply.date = Time.new()
  reply.from = "lecture@some-university.ac.jp"
  reply.subject = NKF.nkf("-j", "某授業レポート受理")
  reply.body = NKF.nkf("-j", msg)
  reply.mime_version = "1.0"
  reply.set_content_type 'text', 'plain', 'charset' => 'iso-2022-jp'
  return reply
end

mail = TMail::Mail.parse(STDIN.read())

if (mail.subject =~ /LECTURE:(\d+)/)
  received = []

  id = $1
  mail.parts.each {|m|
    m.base64_decode()
    fname = m.disposition_param("filename")
    if (/lecture-\d-\d\.txt/ =~ fname)      
      save(id, fname, m.body)
      received << fname
    end
  }

  reply = create_reply(received, mail.create_reply())
  msg = reply.encoded()
  Net::SMTP.start("mailserver", 25) { |smtp|
    smtp.send_mail(msg, reply.from_address, reply.destinations)
  }
else
  #レポート提出メールではなかった
end

*1:私は結構苦労して書きましたが