Project

General

Profile

Actions

一覧表示 アクション

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

ページ表示の流れ

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

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

コントローラの実装

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

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

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

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

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

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

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

ビューの実装

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

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

データが空の場合の対策

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

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

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

テーブルの作成

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

<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, project_foo_path(@project, foo.id) %></td>
</tr>
<% end %>
</tbody>

</table>

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

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

テーブルの各行には各データの ID 番号(foo.id)と題名(foo.subject)を表示しています。
題名は各データの詳細ページ(show)へのリンクにしています。
show のルーティングは次のようになっていました。

         project_foo GET          /projects/:project_id/foos/:id(.:format)          foos#show

show アクションのパス project_foo_path (オプションのルート名 project_foo に _path をつけたもの) へ第一引数(:project_id)にプロジェクトの識別名、第2匹引数(:id)として、データの IDを渡しています。
こうすることによって show アクションでは params[:id] でデータの id 番号を取得することができるようになります。

:project_id に渡しているのは現在のプロジェクトのオブジェクト(@project)ですが、 Redmine の方で @project.identifer を呼び出して、プロジェクトの識別名にしてくれます。

なお、次のようにハッシュを使った URL 指定もできますが、簡単に理解しやすいパスを使った URL 指定をなるべく使っていきます。

{:controller => 'foos', :action=> :show, :project_id => @project, :id => foo.id}

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

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

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

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

リンクは通常 Rails の link_to を使用しますが、ここでは Redmine の link_to_if_authorized メソッドを使用しています。こうしておくことによって new アクションの権限がユーザに無い場合にはリンクは表示されなくなります。
なお、 link_to_if_authorized メッソドの URL 指定はパスに対応していないのでハッシュで指定しています。
また、コントローラは省略しています。コントローラが省略された場合、現在のアクションと同じコントローラが指定されたことになります。

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

一覧表示ページ

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

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


<div class="contextual">
  <%= link_to_if_authorized(l(:label_foos_new), 
                            {:action => 'new', :project_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, project_foo_path(@project, foo.id) %></td>
</tr>
<% end %>
</tbody>

</table>

<% end %>

^ << >>

Updated by NAITOH Jun over 6 years ago · 6 revisions