試行錯誤
まだ全然中身がないので色々実験している。相変わらず本題には入れていない。
私は多数派の安心感を求めて長いものには積極的に巻かれに行く人間なので、Ruby の CGI としてどのような構成が美しいとされるのかガイドラインのようなものがあればとても助かるのだが、考えてみたらそんなものがあるならフレームワークが乱立したりはしていないわな。
index.rb
まず CGI オブジェクト と CGI::Session オブジェクトを引数で持ち回すのをやめてグローバル変数に放り込んだ。
#!/usr/local/bin/ruby -Ku require 'cgi' require 'cgi/session' require 'config' require 'vote' class CGI def redirect(location) puts header({'Status' => '302 Found', 'Location' => location,}) end end File.umask(0066) Dir.mkdir(USER_FILE_PATH) unless File.exists?(USER_FILE_PATH) $cgi = CGI.new $session = CGI::Session.new($cgi, {'session_expires' => Time.now + (60 * 60 * 24 * 5)}) Vote.new.run
私はなるたけグローバルフリーに考える癖が付いているのだが、Diplomacy MOE では盲目的にこだわりすぎて現在進行形で酷い目に遭っているので方針変更。
vote.rb
認証関係の処理は Auth オブジェクトに丸投げ。これで Vote クラスはすっきりした。今後追加される処理もこの調子で委譲しまくれば肥大化は防げそうだ。
require 'forwardable' require 'auth' autoload 'TopPage', 'toppage' autoload 'EditUserPage', 'edituserpage' autoload 'RegisterPage', 'registerpage' autoload 'InformationPage', 'informationpage' class Vote extend Forwardable def_delegators :@auth, :action_login, :action_logout def_delegators :@auth, :action_edituser, :action_edituser_execute def_delegators :@auth, :action_register, :action_register_confirm, :action_register_execute def initialize @auth = Auth.new end def run action = $cgi['action'].to_s if action.size > 0 send('action_' + action) else TopPage.new(@auth).show end end def method_missing(name, *args) $cgi.redirect(BASE_URL) end end
委譲は Forwardable ライブラリを使用。ついでにメソッド名にはリクエストの action パラメータに対応していることをプレフィクスで明示してみた。
auth.rb
Vote クラスから委譲された処理と本来の処理とで今度はこっちが膨れ上がってしまった。もっともこれ以上機能が増える予定はないし、空行込みで 100 行強なら許容範囲として良かろう。
require 'erb' require 'yaml/store' require 'verifyer' class Auth include Verifyer attr_reader :email, :name def initialize @email = $session['email'].to_s if @email.size > 0 && File.exists?(USER_FILE_PATH + @email) db = YAML::Store.new(USER_FILE_PATH + email) db.transaction(true) do @name = db[:name] $session['edituser_name'] = @name unless $session['edituser_name'].to_s.size > 0 end else @email = nil end end def to_html ERB.new(File.read('auth.rhtml'), nil, '-').result(binding) end def logon?; @email.to_s.size > 0 end def action_login return $cgi.redirect(BASE_URL) unless $cgi.referer vote_email = $cgi['vote_email'].to_s vote_pass = $cgi['vote_pass'].to_s begin login(vote_email, vote_pass) $cgi.redirect($cgi.referer) rescue => e info = InformationPage.new(self) info.message = e.message info.show end end def login(email, pass) email = verify_email(email) pass = verify_pass(pass) unless File.exists?(USER_FILE_PATH + email) raise 'メールアドレスが登録されていません。' end db = YAML::Store.new(USER_FILE_PATH + email) db.transaction(true) do if db[:pass] != pass raise 'パスワードが違います。' end end $session['email'] = email end def action_logout $session.delete $cgi.redirect($cgi.referer) end def action_edituser return $cgi.redirect(BASE_URL) unless $cgi.referer return $cgi.redirect(BASE_URL) unless logon? edit = EditUserPage.new(self) edit.error = $session['edituser_error'] if $session['edituser_error'].to_s.size > 0 edit.show $session['edituser_error'] = nil end def action_edituser_execute return $cgi.redirect(BASE_URL) unless $cgi.referer name = $cgi['edituser_name'].to_s pass1 = $cgi['edituser_pass1'].to_s pass2 = $cgi['edituser_pass2'].to_s begin $session['edituser_name'] = name EditUserPage.new(self).execute(name, pass1, pass2) $session['edituser_name'] = nil return $cgi.redirect(BASE_URL) rescue => e $session['edituser_error'] = e.message return $cgi.redirect(BASE_URL + '?action=edituser') end end def action_register return $cgi.redirect(BASE_URL) unless $cgi.referer if logon? $cgi.redirect(BASE_URL + '?action=edituser') else reg = RegisterPage.new(self) reg.error = $session['register_error'] if $session['register_error'].to_s.size > 0 reg.show $session['register_error'] = nil end end def action_register_confirm return $cgi.redirect(BASE_URL) unless $cgi.referer vote_email = $cgi['vote_email'].to_s begin reg = RegisterPage.new(self) reg.confirm(vote_email) reg.show rescue => e $session['register_error'] = e.message $cgi.redirect($cgi.referer) end end def action_register_execute return $cgi.redirect(BASE_URL) unless $cgi.referer vote_email = $cgi['vote_email'].to_s reg = RegisterPage.new(self) reg.execute(vote_email) reg.show end end
登録情報の保存には YAML::Store を使用。アカウントのメールアドレスがそのままファイル名になる。to_html メソッドはほぼ全画面共通のログインフォーム表示用。エラー処理での例外の使い方がかなりお行儀悪いのでどうにかしないといけない。独りで作っていると異常ルートがついつい雑になってしまうのが困りもの。リファラチェックもやるならもう少し真面目にやらないと危ない気がする。
この調子でソースを貼っていけばいくらでも行数が稼げそうだが、まず誰も読んではくれまいな。本日はこれまで。続きは……ないかも知れん。
- 作者: Dave Thomas,Chad Fowler,Andy Hunt,まつもとゆきひろ,田和勝
- 出版社/メーカー: オーム社
- 発売日: 2006/08/26
- メディア: 大型本
- 購入: 7人 クリック: 270回
- この商品を含むブログ (152件) を見る