プロジェクト

全般

プロフィール

GuideIndexAction » 履歴 » リビジョン 4

リビジョン 3 (Mitsuyoshi Yoshida, 2011/07/07 02:47) → リビジョン 4/6 (Mitsuyoshi Yoshida, 2012/01/18 22:43)

h1. 一覧表示 アクション 

 サンプルの各アクションを作っていきましょう。 
 最初にプラグインのトップページである一覧表示を表示する index アクションの実装を行います。 


 h2. ページ表示の流れ 

 ページを表示するまでの流れのイメージをシーケンス図風に書いてみます。 

 !sequence.png! 

 # ユーザのアクション(ページ指定)により Redmine は指定のコントローラを作成します。 
 ** アクションの度にコントローラのオブジェクトが作成されます。このため *インスタンス変数(@)はそのアクション限りでしか使用できません* 。すなわち、index アクションで格納したインスタンス変数の値を show アクションで使うといったことは出来ません。 
 # Redmine は指定されたアクションのメソッドを実行します。 
 ** コントローラ、アクション以外のパラメータは params 変数に格納されます。 
 # アクションメソッドの後、アクションに対応したページが作成されます。 
 ** コントローラ内で html の埋め込みコードが評価されます。このため *コントローラからビューへのデータの受け渡しにはインスタンス変数* を使うことが出来ます。 
 # 生成したページをユーザに表示します。 



 h2. コントローラの実装 

 コントローラ(app/controller/foo_app/controllers/foos_controller.rb) の index メソッドを実装します。 index ではデータベース(foos テーブル)から現在のプロジェクトに一致するデータ(foo)のリストを取得します。 

 <pre><code class="ruby"> 
   def index 
     @foos = Foo.find(:all, :conditions => ["project_id = #{@project.id} "]) 
   end 
 </code></pre> 

 モデルクラスの *Foo#find* のクラスメソッドにより、条件に一致するデータを取得して、 *@foos* のインスタンス変数に格納しています。 

 第一引数では :all 、 :first などのシンボルを指定します。 

 |_. シンボル |_. 説明 |_. 戻り値 | 
 | :all | 条件に一致したすべてのデータを取得 | モデルオブジェクトの配列 | 
 | :first | 条件に一致した最初のデータを取得 | モデルオブジェクト | 

 第二引数はハッシュを受け取るオプションです。ここで *:conditions* を使って条件を指定します。 
 foo には属するプロジェクトの識別のためにプロジェクトの ID 番号を格納する [[GuideModel|project_id]] のメンバを持っていました。これが現在のプロジェクトの id と一致するということを条件にしています。 index メソッドの前には必ず [[GuideForProject|find_project]] が呼ばれて、@project に現在のプロジェクトのオブジェクトが格納されています。 

 実は :conditions の指定は SQL 形式での指定となるので、けっこう複雑です。ただ、フィルタ機能などを付けなければ、実際にプラグインを作成される場合もこのまま書いてもらえば十分だと思います。 
 検索条件の指定方法は機会があればそのうち詳しく書きたいと思います。 

 h2. ビューの実装 

 次にビュー (app/views/foos/index.html.erb) を実装します。 

 コントローラで設定した @foos はそのままビューでも使用できます。これにモデルのオブジェクトとしてレコードの情報が配列で入っているので、 html のテーブルを使って一覧表示します。 


 h3. データが空の場合の対策 

 データは空の場合があります。最初に @foos が空かどうかチェックして、空の場合はその内容のエラーメッセージを表示する必要があります。 

 <pre><code class="rhtml"> 
 <% if (@foos.blank?) %> 
   <p class="nodata"><%= l(:label_no_data) %></p> 
 <% else %> 
    データのテーブル 
 <% end %> 
 </code></pre> 

 空のチェックには Rails が Object クラスに追加している *blank?* のメソッドを使用しています。 empty? メソッドではオブジェクトが nil の場合例外が発生してしまいますが、 blank? であれば、 nil でもエラーとなりません。配列や文字列が空かチェックする場合は基本的にこちらを使う方がいいでしょう。 blank? の逆のメソッドで *any?* というのもあります。 
 エラーメッセージ :label_no_data は Redmine で定義されているメッセージで、 class で指定している nodata も Redmine で定義されている CSS のクラスです。これらを使うことにより、 チケットのような Redmine の他のページと同じスタイルで表示できるようになります。 

 h3. テーブルの作成 

 @foos が空でなければテーブルを作成します。テーブルに表示する要素は foo の *ID 番号(id)* と *題名(subject)* にします。 

 <pre><code class="rhtml"> 
 <table class="list"> 

 <thead><tr>   
 <th>#</th> <th><%=h l(:field_subject) %></th> 
 </tr></thead> 

 <tbody> 
 <% @foos.each do |foo| %> 
   <tr class="<%= cycle('odd', 'even') %>"> 
   <td><%= foo.id %></td> 
   <td><%= link_to(foo.subject, {:action=> :show, :project_id :id => @project, :id :foo_id => foo.id} ) %></td> 
 </tr> 
 <% end %> 
 </tbody> 

 </table> 
 </code></pre> 

 まず、テーブルのヘッダ行を出力して後テーブルの各行を *@foos.each* でループをまわして作成しています。 

 テーブルの *list*, *odd*, *even* も Redmine で定義された CSS のクラスで Redmine にあわせたスタイルにすることが出来ます。 odd, even は行の色を一つおきに変えていくためのもので、 Rails の *cycle* メソッドでループをまわす度にクラスを切り替えています。 

 テーブルの各行には各データの ID 番号(foo.id)と題名(foo.subject)を表示しています。 
 題名は各データの詳細ページ(show)へのリンクにしています。このときデータの 題名は各データの詳細ページ(show)へのリンクにしています。このときプロジェクトの識別名を ID として、データの id*:id* として、 プロジェクトの識別名を *:project_id* *:foo_id* のパラメータとして渡しています。こうすることによって show アクションでは params[:id] params[:foo_id] でデータの id 番号を取得することができるようになります。 
 :project_id :id に渡しているのは現在のプロジェクトのオブジェクト(@project)ですが、 Redmine の方で @project.identifer を呼び出して、プロジェクトの識別名にしてくれます。 
 また、コントローラは省略しています。コントローラが省略された場合、現在のアクションと同じコントローラが指定されたことになります。 

 h3. new アクションのリンクを追加 

 一覧表示ページから新規作成ができるようにします。そのためには new アクションのリンクを追加する必要があります。 

 <pre><code class="rhtml"> 
 <div class="contextual"> 
   <%= link_to_if_authorized(l(:label_foos_new),  
                             {:action => 'new', :project_id :id => @project},  
                             :class => 'icon icon-add') %> 
 </div> 
 </code></pre> 

 new へのリンクは *contextual* のクラスで指定された div 中に書きます。これにより Redmine の他の文書やファイルのページのようにページの右上に表示することが出来ます。リンクを表示する位置は CSS のスタイルで決められているので、 記述する位置は index.html.erb ファイル中のどこに書いてもかまいません。 

 リンクは通常 Rails の link_to を使用しますが、ここでは Redmine の *link_to_if_authorized* メソッドを使用しています。こうしておくことによって new アクションの権限がユーザに無い場合にはリンクは表示されなくなります。 

 また、リンクのクラスには *"icon icon-add"* を使用して、追加用のアイコンを表示しています。これについての詳しい説明は [[TipsUseIcon|プラグイン Tips]] を見てください。 


 h2. 一覧表示ページ 

 それでは、 Redmine で一覧表示のページを表示してみましょう。 
 まだ、データが何もないので空データのメッセージが表示されています。 

 !action_index.png! 

 この章で作成した index.html.erb ファイルの全文は次のようになります。 

 <pre><code class="rhtml"> 

 <div class="contextual"> 
   <%= link_to_if_authorized(l(:label_foos_new),  
                             {:action => 'new', :project_id :id => @project},  
                             :class => 'icon icon-add') %> 
 </div> 

 <h2> <%=h l :label_standard %> </h2> 

 <% if (@foos.blank?) %> 
   <p class="nodata"><%= l(:label_no_data) %></p> 
 <% else %> 

 <table class="list"> 

 <thead><tr>   
 <th>#</th> <th><%=h l(:field_subject) %></th> 
 </tr></thead> 

 <tbody> 
 <% @foos.each do |foo| %> 
   <tr class="<%= cycle('odd', 'even') %>"> 
   <td><%= foo.id %></td> 
   <td><%= link_to(foo.subject, {:action=> :show, :project_id :id => @project, :id :foo_id => foo.id} ) %></td> 
 </tr> 
 <% end %> 
 </tbody> 

 </table> 

 <% end %> 
 </code></pre> 


 --- 

 | [[プラグイン開発ガイド|^]] | [[GuideI18n|<<]] | [[GuideNewAction|>>]] |