Webフレームワークの新しい波 Waves探訪記

第3回 シンプルなWebアプリを作る(その1)

この記事を読むのに必要な時間:およそ 4.5 分

一覧の表示

モデルWordの全レコードは@wordsとして自動的に設定されます。

viewメソッドは,⁠view モデル名, ビュー名, ビューに渡すインスタンス変数名=>変数」と記述します。ここではwordモデルに対してsummaryというビューを使っています。summaryビューでは@wordというインスタンス変数が使え,その値はここでwordとして取り出しているWordテーブルの各エントリになります。

したがって,summaryビューを作る必要があります。templates/word/summary.mabです。

個々のエントリのテンプレート

div.text do
  p @word.text
  p.date @word.created_on.strftime("%Y-%m-%d %H:%M") if @word.created_on
end

summaryビューは他のビューから呼ばれることを前提にしているので,layoutは指定しません。前述したように呼び出し元からWordのエントリが渡されて,@wordとして参照できるようになっています。

これで一覧が表示できるようになります。URLとしては/word/listではなく/wordsでOKです。Wavesのちょっと賢い機能の一つです。

テスト実行してみる

ちょっと動作を確認してみましょう。waves-serverコマンドを使って,ウェブサーバを起動します。

サーバの起動

tw% waves-server
I, [2008-04-24T23:41:36.589731 #17044]  INFO -- : ** Waves Server Starting ...
I, [2008-04-24T23:41:36.617656 #17044]  INFO -- : ** Waves Server Running on 0.0.0.0:3000
I, [2008-04-24T23:41:36.618151 #17044]  INFO -- : Server started in 27 ms.

ブラウザから(同じマシンで開発していれば)⁠http://localhost:3000/words」を入力します。

一覧表示画面

一覧表示画面

エントリの追加

フォームは「form :action=>'/words', :method=>'post'」となっています。つまりwordsというURLにデータをポストしています。このRESTスタイルの呼び出しを,Wavesは「wordテーブルへの追加」と解釈します。実際に追加されるフィールドはtextareaのnameフィールド(word.text)で決まります。wordsテーブルにエントリが追加され,このテキストエリアの値がtextフィールドにセットされます。

ここで注意すべきなのは,RESTスタイルの振る舞いはconfigurations/mapping.rbで設定されているので,mapping.rbを書き換えることでこれを止めることも可能だということです。

さて実際にエントリを追加してみるとエラーになります。デフォルトの振る舞いとして,レコードの追加後にeditorビューが呼ばれるからです。

レコード追加後に一覧に戻る

レコード追加後に一覧に戻るようにするにはconfigurations/mapping.rbにカスタム処理を記述します。

デフォルトのマッピングを変える

module Tw
  module Configurations
    module Mapping
      extend Waves::Mapping
      # your custom rules go here
      path %r{^/words/?$}, :method=>:post do
        use(:word)
        word = controller{create}
        redirect('/words')
      end
      include Waves::Mapping::PrettyUrls::RestRules
      include Waves::Mapping::PrettyUrls::GetRules
    end
  end
end

pathメソッド以降が新たに追加した部分です。

まずpathのパラメータとしてカスタム処理を設定したいURLを正規表現の形で記述します。今回は/entriesにポストしたときの振る舞いなので「path %r{^/words/?$}, :method=>:post」となります。⁠use(:word)」で利用するモデルを指定しています。controllerは,useで設定されているモデルのコントローラを返します。パラメータにブロックを1つとり,コントローラのメソッドを呼び出しています。⁠controller{create}」はWordコントローラのcreateメソッドを呼び出したことになります。これでレコードが追加されました。最後に「redirect('/words')」で一覧に戻ります。

これでエントリを追加できるようになりました。

コントローラの振る舞いを変える

エントリの一覧ではなく,個々のエントリを表示させるには個々のエントリを示すキーが必要です。Wavesではデフォルトでnameフィールドが使われます。例えば「/word/first-word」というURLで呼び出すと,wordsテーブルのnameフィールドが'first-word'であるようなレコードが返るのです。しかし今回はnameフィールドを作ってませんし,マイクロブログでひとつひとつのエントリに名前をつけるというのは非現実的なので,Rails風にレコードのidを使うことにします。

コントローラにはデフォルトの振る舞いを記述してあるファイルがあります。controllers/default.rbです。default.rbには個々のエントリを探すfindメソッドがあり「def find( name ); model[ :name => name ] or not_found; end」と定義されています。レコードのnameフィールドで検索しているのです。今回はnameフィールドは使わないので,ここを「def find( name ); model[ :id => name ] or not_found; end」と書き換えます。これでRails風にidで個々のレコードを指定できます。

個別のエントリの表示

templates/show.mabを作ります。

個別のエントリを表示する

layout :default, :title=>@word.id do
  p @word.text
  a 'home', :href=>'/words'
end

これで「http://localhost:3000/word/1」などとしてエントリを個別に表示できるようになりました。

個別のエントリ表示

個別のエントリ表示

まとめと次回の予定

Wavesの強力なデフォルト機能と,動的にモデルやコントローラを作り出す機能のおかげで,ビューと設定ファイルの書き換えだけでも一通りのことができます。

次回は認証機能などを追加していきます。

著者プロフィール

松永肇一(まつながけいいち)

株式会社ライフメディア 創造推進部プロジェクトマネージャ。東京都出身。千葉大学工学部での卒論テーマは人工知能関連だったが,富士通に入社後はPCのソフトウェア開発に関わる。"GNU for Towns"のために,リチャード・ストールマンに会いにいくような妙な仕事を経て現職。Ruby on Railsを使ってWebアプリを開発する毎日。ブログは「ma2の日記」。

URLhttp://d.hatena.ne.jp/ma2/