[coreserve][Amrita2] Amrita2化
Rubyカンファレンスのネタにする為に、できあがった画面をひとつAmrita2化してみました。
やったのは、こちらの一覧表示画面。この画面は、ゲスト/クライアント/カウンセラーで、それぞれ少しづつ違う画面になるので、ビューは次のような感じで、case文がたくさん含まれています。
<h1>カウンセリング予約システム</h1> <br /> <p> <%= "#{current_user.lastname} さん " if current_user %> カウンセリング予約システムへようこそ </p> <ul> <%- case current_user -%> <%- when nil -%> <li><%= link_to 'ログイン', :controller => 'client', :action => 'login' %></li> <li><%= link_to '新規ユーザ登録', :controller => 'client', :action => 'signup' %></li> <%- when Client -%> <li><%= link_to 'ログアウト', :controller => 'client', :action => 'logout' %></li> <li><%= link_to 'ユーザ情報変更', :controller => 'client', :action => 'edit' %></li> <%- when Counselor -%> <li><%= link_to 'ログアウト', :controller => 'client', :action => 'logout' %></li> <li><%= link_to 'ユーザ情報変更', :controller => 'client', :action => 'edit' %></li> <li><%= link_to '管理', :controller => 'reservation', :action => 'index' %></li> <%- end -%> </ul>
Amrita2バージョンのテンプレートのこれに対応する部分は、
<h1>カウンセリング予約システム</h1> <br /> <p> <span id='user'> <span id='lastname' /> さん </span> カウンセリング予約システムへようこそ </p> <ul> <li id='navi_links'><a id='link' amrita:type='link' /></li> </ul>
と、かなりスッキリしています。ロジックはコントローラに移っているわけです。そこを抜き出すと
@user = current_user case current_user when nil @navi_links = [ { :link => [ url_for( :controller => 'client', :action =>'login'), 'ログイン' ] }, { :link => [ url_for( :controller => 'client', :action =>'signup'), '新規ユーザ登録' ] } ] when Counselor @navi_links = [ { :link => [ url_for( :controller => 'client', :action =>'logout'), 'ログアウト' ], ....
一覧の所は、最後にリンクの表示が、ユーザ種別とセッションの状態の二重の分岐になっているのでかなりややこしいですが
<%- for counseling_session in @counseling_sessions -%> <tr> <td><%=h counseling_session.counselor_name %></td> <td><%=h counseling_session.status_j %></td> <td><%=h human_attribute_value(counseling_session, 'start') %></td> <td><%=h human_attribute_value(counseling_session, 'end') %></td> <td><%=h human_attribute_value(counseling_session, 'place') %></td> <td><%=h human_attribute_value(counseling_session, 'memo') %></td> <%- case counseling_session.status -%> <%- when :free -%> <%- case current_user -%> <%- when nil,Client -%> <td><%= link_to '予約', :action => 'reserve', :id => counseling_session %></td> <%- else -%> <td /> <%- end -%> <%- when :reserved -%> <%- if current_user == counseling_session.client -%> <td><%= link_to 'キャンセル', :action => 'cancel', :id => counseling_session %></td> <%- else -%> <td /> <%- end -%> <%- else -%> <td /> <%- end -%> </tr> <%- end -%>
これも、Amrita2では、次のようにスッキリ。
<tr id='counseling_sessions'> <td id='counselor_name' /> <td id='status' /> <td id='start' /> <td id='end' /> <td id='place' /> <td id='memo' /> <td id='navi'> <a id='navi_link' amrita:type='link' /> </td> </tr>
もちろん、対応するロジックはコントローラの中にあるわけですが。
@counseling_sessions = sessions.collect do |s| { :counselor_name => s.counselor_name, :status => s.status_j, :start => human_attribute_value(s, 'start'), :end => human_attribute_value(s, 'end'), :memo => human_attribute_value(s, 'memo'), :place => human_attribute_value(s, 'place'), :navi => { :navi_link => case s.status when :free case current_user when nil,Client [ url_for(:action => 'reserve', :id => s), '予約'] else end when :reserved if current_user == s.client [ url_for(:action => 'cancel', :id => s), 'キャンセル', ] end end } } end
この方式だと、動的な要素を抜き出して検証することが可能なので、テストがしやすいです。
def test_index_for_client get :index, {}, :user => @cl1 assert_response :success assert_equal ["http://test.host/amrita/cancel/10003", "キャンセル"], assigns(:counseling_sessions)[0][:navi][:navi_link] assert_equal ["http://test.host/amrita/reserve/10002", "予約"], assigns(:counseling_sessions)[1][:navi][:navi_link] assert_equal ["http://test.host/amrita/reserve/10001", "予約"], assigns(:counseling_sessions)[2][:navi][:navi_link] end
それから、ERbの埋め込みは、やはりRailsと相性がいいと思います。jascaffoldで生成したテンプレートには、次のようにHelperメソッドを利用したページ遷移のリンクがあります。
<%= pagination_links @counseling_session_pages %>
ここは、次のように、Amrita2テンプレートの中にERbテンプレートを埋め込んで対応しました。
<span id='page_navi'><![CDATA[ <%= pagination_links $_[:pages] %> ]]></span>
コントローラのロジックはこのとおり。
session_pages, sessions = paginate :counseling_sessions, list_param ..... @page_navi = { :pages => session_pages }
こういうAmrita2向けのデータ(プレゼンテーションオブジェクト)の設定は、コントローラでなく、Helper モジュールの中に書いた方がいいかもしれません。
Railsのビュー(ERbテンプレート)は、ビューロジックとプレゼンテーションが混在してしまうと思います。Amrita2を使うことで、このように、ビューロジックとプレゼンテーションを分離して、ビューロジックだけをテストすることが可能になります。