素人がRubyでcgiを書いてみたよ!>< - ちょっとした携帯振り分けプログラム

最近WORD編集部内で「スーパーコーディングタイム」なるものが流行っていたので、少し参加してました。
コーディングよりも、FreeBSDのkernel/Worldをmakeしている画面を眺めるのが好きなので、ここ数週間はずっとFreeBSDのセットアップをしていたのですが、大体弄りたい所は弄り終わったのでapacheでも入れてコーディング大会に参加してみる事にしました。
最初は「Perlでもやっか、id:amachangPerlやろうぜPerlとか言ってたし」と思いましたが、横をみたらid:viverとか座っていたので「これはRubyを使わないとBSDを飛ばしてMandrivaを入れられてしまう」と思い、Rubyを使いました。
あ、でも勿論OSはFreeBSDですよ。

BSDvimがあれば幸せ。

んで。

とりあえず、今某サイトが出来合いのcgiを組み合わせてカオスっているので、それをリプレースしようとキャリア別の振り分けcgiでも書くか、という事に。
id:amachangが「恥ずかしくても公開するのが大事だよ!><」と言っていたし、id:viverの口癖が「とりあえず公開しちまえばいいんですよ」なので、貼り付けてしまう事にします。

以下src。

index.cgi::本体
#!/usr/bin/env ruby

# 自作ライブラリ読み込みするお
$LOAD_PATH.push File.dirname(__FILE__) + '/lib/'

require 'cgi'

require 'page'
require 'setting'
require 'client_info'
require 'view'

def main
  cgi  = CGI.new
  info = ClientInfo.new
  info = info.get(cgi.user_agent)

  pagePath = PagePath.new
  pagePath = pagePath.get(info.carrier, info.client)

  View.new(pagePath)
end

main
client_info.rb::キャリア判別モジュール(lib/に入れる)
#
# client_info.rb - キャリア判別モジュール
#
# carrier:: キャリアの内容が入る
#   - docomo, softbank, ez, willcom, pc
#
# client:: 端末の種類
#   - old, new
#

class ClientInfo
  def get(ua)
    userAgent = ua.to_s.downcase
    client = :old

    # Ez
    if userAgent.include?("up.browser")
      carrier = :ez
      if /^kddi-/ =~ userAgent
        client = :new
      end

      # DoCoMo
    elsif userAgent.include?("docomo")
      carrier = :docomo
      if userAgent.include?("(c100")
        client = :new
      end

      # SoftBank
    elsif userAgent.include?("j-phone") || userAgent.include?("vodafone") || userAgent.include?("softbank")
      carrier = :softbank
      if !userAgent.include?("j-phone")
        client = :new
      end

      # Willcom
    elsif userAgent.include?("ddipocket") || userAgent.include?("willcom")
      carrier = :willcom
      client = :new

      # それ以外は暫定でPCとするお
    else
      carrier = :pc
      client = :new
    end

    return Info.new(carrier, client)
  end

  class Info
    def initialize(carrier, client)
      @carrier = carrier
      @client = client
    end
    attr_reader :carrier, :client
  end
end
page.rb:: キャリア別ページ選択ライブラリ(lib/ 以下)
#
# page.rb キャリア別ページ選択ライブラリ
#

class PagePath
  def get(carrier, client)

    carrier = carrier.to_s.upcase
    client = client.to_s.upcase

    #### Envから設定読み込み####
    # carrier, clientから定数名を生成
    mode = (carrier)  + '_' + (client)

    # PCもぉど
    if carrier == "PC" && Env.constants.include?('PC') && !Env::PC.empty?
      page = Env::PC
      # キャリア情報のみ設定
    elsif Env.constants.include?(carrier) && Env.const_get(carrier)
      page = Env.const_get(carrier)
      # クライアント情報のみ設定
    elsif Env.constants.include?(client) && Env.const_get(client)
      page = Env.const_get(client)
      # キャリアとクライアント情報
    elsif Env.constants.include?(mode)
      page = Env.const_get(mode)
    end

    return page
  end
end
view.rb::リダイレクト用ライブラリ(lib/ 以下)
#
# view.rb 対象のファイルにリダイレクト
#
class View
  def initialize(pagePath)
    body = "Location: #{pagePath}\n\n"
    puts body
  end
end
setting.rb::設定用ファイル(lib/ 以下)
#
# (キャリア名)_(クライアント)
#   - キャリア名:: IMODE, EZWEB, WILLCOM, PC
#   - クライアント:: NEW, OLD
#

module Env
  # i-mode端末用設定
  IMODE_NEW = ""
  # Ezweb端末用設定
  EZ_NEW = "./ez.html"
  # Willcom端末用設定
  WILLCOM = ""
  # PC用設定
  PC = "./pc.html"
  # 旧機種用ページ
  OLD = ""
end

そんで。

view.rbに手を加えてERB使ってテンプレート読み込みにでもすれば、カウンタ表示とか懐かしい機能が実装できるね><
単純リダイレクトと、ERBのテンプレート読み込み、どちらがいいかな?両方実装しちゃって設定から切り替え式にしちゃえばいいかな><

感想

150行程度書くのに4,5時間掛かるとか鬱です><
でも、家帰ると本読んじゃったりはてな巡回・2ch巡回位をずっとしてしまうので、皆でコーディング大会ってのは良いです。
教えあいもしやすいですしね!><(まぁ、一方的に私は聞く方なんですが)

因みに

UserAgentで振り分けてるのは

  • ipで振り分けると、こっそりとipが追加されていたときに気づかない事がある
  • host名で振り分けると、逆引きが出来ない環境で困ることがある
  • 別に、UA偽装されても困るコンテンツじゃなーいしー(某天使が出てくる欝アニメOPソング風に)

って事です><
素人の汚いソースでお目汚しすいませんでした><