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

第6回 Twの完成と拡張

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

フォローUIを作る

次に任意のユーザをフォローしたり,フォローからはずしたりするUIを作ります。 前述の発言一覧画面に,ユーザのフォロー/リムーブ(フォローをやめる)ができるUIを追加します。

ビュー

templates/word/list.mabのリストの後半に以下のような部分があります。 これがフォロー用のUIです。

フォロー用のUIの呼び出し

table.friends do
  tr do
    th(:colspan=>2){"users"}
  end
  @users.each do |user|
    next if user.name == @me.name
    view :word, :show_user, :user=>user, :me=>@me
  end
end

実際のビューはtemplates/word/show_user.mabが呼ばれています。ファイルを作成して,以下のようにします。

フォロー用のUI

tr do
  td @user.name
  td {
  if @me.following_users[:name=>@user.name] then
    a 'remove', :href=>"/user/#{@user.name}/remove"
  else
    a 'follow', :href=>"/user/#{@user.name}/follow"
  end
  }
end

ここでは全ユーザをリストアップして,すでにフォロー済みのユーザには"remove",まだフォローしていないユーザには"follow"のアクションへのリンクを生成しています。ここのアクション呼び出しのURLはWaves風ではなく,Rails風になっていますね。というわけで,このURLをWavesが解釈できるようにする必要があります。

mapping.rbの修正

デフォルトで使えるREST型のルールを使ってもいいのですが,ここでは自前のルールを定義してみます。追加するアクションはfollowとremoveの2つで,ちょっとRails風に「/words/(ユーザ名)/follow」⁠/words/(ユーザ名)/remove」と呼べるようにしてみます。

まずconfigrations/mapping.rbを修正して,上記のURLを受け取るようにします。

Rails風のURLを受け付けるようにしたmapping.rb

module Tw
  
  module Configurations
    
    module Mapping
      extend Waves::Mapping
      # your custom rules go here
      path %r{^/user/(\w+)/(follow|remove)/?$}, :method=>:get do |name, action|
        use(:user)
        controller{self.send(action,name)}
        redirect('/words')
      end
      path %r{^/words/?$}, :method=>:post do
        use(:word)
        controller{create}
        redirect('/words')
      end
      include Waves::Mapping::PrettyUrls::RestRules
      include Waves::Mapping::PrettyUrls::GetRules
    end
    
  end
  
end

followとremoveの場合処理はほとんど同じなので,1つのpathのブロックに処理をまとめました。,まずトリガーとなるURLパターンを定義します。正規表現でURLに対してマッチングを行うことができるのですが,このとき後方参照用の部分が,そのままブロックの引数に渡されます。例えば「%r{^/user/(\w+)/follow/?$}」と指定すると,/user/(任意の文字列)/follow というパターンにマッチして,その文字列がブロックの引数 name で参照できます。ブロック内では「use(:user)」で,Userモデルを指定します。⁠controller{self.send(action,name)}」で,Userコントローラのアクション(followかremove)がnameをパラメータとして起動します。最後に一覧表示画面である「/words」にリダイレクトしています。

アクションの追加

最後に実際のアクションを書きます。 controller/user.rbを以下のようにします。Wavesによって自動生成したものに手を入れたものです。

ユーザのフォロー・リムーブのアクション

module Tw
  
  module Controllers
  
    class User
      
      include Waves::Controllers::Mixin
      
      def attributes; params[model_name.singular.intern]; end
      
      def all; model.all; end

      def find( name ); model[ :name => name ] or not_found; end
    
      def create; model.create( attributes ); end
    
      def update( name )
        instance = find( name )
        instance.set( attributes )
        instance.save_changes
      end
    
      def follow(name)
        @me = Tw::Models::User[:name=>request.env['REMOTE_USER']]
        user = find(name)
        @me.add_following_user(user) unless @me.following_users[:name=>user.name]
      end
      
      def remove(name)
        @me = Tw::Models::User[:name=>request.env['REMOTE_USER']]
        user = find(name)
        @me.remove_following_user(user) if @me.following_users[:name=>user.name]
      end
      
    end

  end

end

フォローに追加するメソッドはadd_following_user,リムーブするアクションはremove_following_userです。重複して追加や,存在しないユーザを削除しないように,直前にチェックをしています。これはモデル側でチェックすることも可能です。

cssの追加

第4回で追加したbase.cssに適当な記述をすれば,見栄えもよくできるでしょう。自分の発言と他人の発言は異なるcssクラスなので色分けも可能です。簡単にcssを設定したサンプルのスクリーンショットは,以下のようになります。

cssを設定した画面

cssを設定した画面

まとめと次回の予定

Twitter風簡単アプリTWはこれでほぼ完成です。次回はWavesの今後のロードマップなどを解説したいと思います。

著者プロフィール

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

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

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