Jewel-mmo開発日記

RubyでMMORPGを作る過程を記録する日記。 Yokohama.rb 発起人。
2008-03-22

[Bilbo]BilboのMVC

http://mt.endeworks.jp/d-6/2008/03/db-1.html

BilboはDBを使わないけどMVCで実装している。

良い機会なのでBilboの超シンプルなMVCの実装を紹介。 このMVCを実現してるコア(bilbo.rb)は81行。

モデル

日記の記事はモデルとして管理される。具体的にはEntryクラスが記事を扱うモデルである。

entries = Entry.find('200803', :limit => 5)

こんな風にすると2008年3月の記事オブジェクトを5個取り出すことができる。

このEntryクラスの実装は30行。 この30行には、記事をHTMLに変換するコンパイラの登録と変換処理も含まれている。 このEntryクラスはBilboにとって最大の機構。30行なんて長すぎるのでコードは省略。

記事オブジェクトは次のようにしてHTML化できる。

entries.first.to_html

原稿のコンパイラは設定ファイル(bilborc)で指定する。 次のコードはHikiDocを登録する例。

require 'misc/hikidoc.rb'
Entry.add_compiler('.txt') {|entry|
  HikiDoc.to_html(entry.body, :level => 2)
}

拡張子「.txt」の原稿をHikiDocでHTML化する。

ビュー

ビューはいたってシンプル。4行で実装されている。

def render_view(name, b = binding)
  erb = Plugin.views[name] || (chdir(:views) { File.read("#{name}.html.erb") })
  ERB.new(erb).result(b) rescue "<h3>ViewError in #{h name}</h3>#{h $!}<pre>#{$@.join("\n")}</pre>"
end

HTMLテンプレートをERBにてレンダリング。

コントローラ

これも短いので、コードを全行貼ってしまったほうが話が早い。

class Controller
  def list
    @entries = Entry.find(params[:date] || '20',
                          :limit => (params[:limit] || config[:limit] || 5).to_i,
                          :page => (params[:page] || 0).to_i)
    render(:list)
  end

  def render(action)
    render_view(:layout) { render_view(action) }
  end
end

デフォルトのアクションとしてlistを定義してあって、あと基本描画にレイアウトファイル(layout.html.erb)にアクション用のテンプレートを埋め込む。

そしてこのコントローラを呼び出すのが以下の部分。 CGIから渡されたactionパラメータをもとにControllerクラスに定義されているメソッドを呼び出す。

def default_action
  :list
end

def action_name # support: ruby 1.8 and 1.9
  action = (params[:action] || params.index(nil) || 'list').to_sym
  Controller.instance_methods(false).map(&:to_sym).include?(action) ? action : default_action
end

def bilbo_context
  Plugin.load
  Controller.new.__send__(action_name)
end

プラグインの中でControllerクラスのインスタンスメソッドを定義してやれば、 それがアクションとしてすぐに呼び出せてしまう。 よってプラグインによる機能追加かがとっても容易。