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

第4回 Twitter風WebアプリケーションTwを強化する

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

コントローラを作る

前回までに,ビューを作るかデフォルトを修正するだけで,Wavesは様々なことができることを示しました。今回は一歩進んで独自のモデルやコントローラを作ってみます。

まずはWordコントローラを作ってみましょう。前回,controllers/default.rbを書き換えて,nameフィールドではなく,idフィールドでレコードを探すように修正しましたが,これをWordモデル限定の動作にして,他のモデルはWavesのデフォルトである「nameフィールドの値でレコードを見つける」にしたいからです。

default.rbを元に戻す

まず,controllers/default.rbの動作を元に戻してください。

default.rbの前回修正部分

def all; model.order(:created_on.desc).all; end
def find( name ); model[ :id => name ] or not_found; end

default.rbの動作を戻す

def all; model.all; end
def find( name ); model[ :name => name ] or not_found; end

この変更により,Twアプリケーションは正常に動作しなくなります。そこで,以下の修正を行ってください。

Wordコントローラを作る

Wordコントローラを作る

rake generate:controller name=word

生成されたcontrollers/word.rbを上記の逆に修正します。これでWordモデルの検索動作だけがidフィールドに対して行われます。Twアプリケーションも無事動くようになるはずです。

WavesのREST動作

前回も簡単に述べましたが,Wavesがデフォルトで提供しているREST動作やnameフィードでレコードを検索する動作は,デフォルトルールとしてconfigrations/mapping.rbで指定されています。「include Waves::Mapping::PrettyUrls::RestRules」「include Waves::Mapping::PrettyUrls::GetRules」です。前者がREST動作を規定して,後者がnameフィールドによる検索を規定しています。デフォルトのルールが不満なら,mapping.rbからルールを削除して,自前で記述することも可能です。

include Waves::Mapping::PrettyUrls::RestRule

RestRuleをincludeすると,以下の3つの処理が使えるようになります。

POST /リソース        # 新しいリソースを追加する
POST /リソース/名前    # 指定の名前のリソースを更新する
DELETE /リソース/名前  # 指定の名前のリソースを削除する

Twアプリケーションで'/words'というURLに対してフォームの内容をPOSTすると,新規にWordレコードが生成されるのが,RestRuleの機能です。

include Waves::Mapping::PrettyUrls::GetRules

GetRulesをincludeすると,以下の処理が使えるようになります。

/リソース(複数形)      # リソースの全リストを取得する
/リソース/名前        # 指定の名前のリソースを取得する
/リソース/名前/editor # 指定のリソースの編集画面を呼び出す

Twアプリケーションで'/words'というURLを呼び出すと,Wordテーブルの全レコードを取得して,templates/word/list.mabが呼び出されるのがGetRulesの機能です。

ユーザと関連を追加する

Twアプリケーションは今のままではアクセスした人の発言がそのままリストされるだけなので,ユーザ毎に発言をまとめる機能を追加します。そのためにUserモデルを追加して,ユーザと発言の関連も追加します。

Userモデルを追加する

次に認証を追加することを考慮して,ユーザ名とパスワードを格納するテーブルを作ります。

Userテーブルのマイグレーションを生成する

rake schema:migration name=add_user

schema/002_add_users.rbを以下のように修正します。

Userテーブルのマイグレーションを修正する

class AddUsers < Sequel::Migration
  def up
    create_table :users do
      primary_key :id
      text :name, :unique => true, :null => false
      text :password, :null => false
    end
    add_column :words, :user_id, :foreign_key, :table => :users
  end
  def down
    drop_table :users
    drop_column :words, :user_id
  end
end

Usersテーブルはid,name,passwordフィールドを持ちます。nameフィールドはユニークでなければなりません。また,発言は発言者に属するので,Wordsテーブルにuser_idフィールドを追加します。「rake schema:migrate」でマイグレーションを実行しましょう。テーブルが生成されます。次にWordモデルとUserモデルを作り,両者の関連を設定します。

WordモデルとUserモデル

rake generate:model name=word
rake generate:model name=user

models/word.rbを以下のように修正します。

Wordモデルにmany_to_oneを設定する

module Tw
  module Models
    class Word < Sequel::Model(:words)
      many_to_one :user, :class=>Tw::Models::User
      after_create do
        set(:created_on => Time.now) if columns.include? :created_on
      end
      before_save do
        set(:updated_on => Time.now) if columns.include? :updated_on
      end
    end
  end
end

一人のユーザが複数の発言を所有するので「many_to_one :user, :class=>Tw::Models::User」が必要になります。Railsと異なり,クラスまで指定する必要があります。逆にUserモデル(models/user.rb)には,「one_to_many :words, :class=>Tw::Models::Word」を追加してください。これでUserモデルとWordモデルの間に関連が設定されました。

著者プロフィール

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

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

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

コメント

コメントの記入