キーワードをクリックしたら、そのキーワードで絞り込むようにしたい!

昨日の追加作業

昨日、詳細表示にキーワード項目を表示するようにしていなかったので、追加しておいた。現在のshow.rhtmlはこんな状態。

ビュー show.rhtml
<% for column in Software.content_columns %>
<p>
  <b><%= column.human_name %>:</b>
  <% if @software.send(column.name) %>
      <%= link_to_if column.name == 'url',
                     h(@software.send(column.name)), 
                     URI.encode(@software.send('url'))  %>
  <% end %>
</p>
<% end %>

<p>
<b>Keyword:</b>
<%= h(@software.keyword.name) unless @software.keyword_id == nil %>
</p>

<%= link_to 'Edit', :action => 'edit', :id => @software %> |
<%= link_to 'Back', :action => 'list' %>

以上で、昨日の追加作業は終了。

キーワードにリンクを設定

まず、キーワードにリンクを設定した。list.rhtmlのキーワードを表示している箇所を以下のように変更した。

ビュー list.rhtml
<td><%= link_to h(software.keyword.name), 
                 :action => 'list', 
                 :keyword_id => software.keyword_id unless software.keyword_id == nil %></td>

リンク先はlistメソッドで、付加情報としてkeyword_idというキーにkeyword_idフィールドの数値を設定してURLに付加している。

出来上がったリンクをクリックすると、以下のURLが表示される。

webブラウザのURL表示
http://0.0.0.0:3000/softwares/list?keyword_id=1

?は区切りマークで、その後のkeyword_id=1が付加情報になる。

付加情報はどうやって取り出すのか?

http://0.0.0.0:3000/softwares/listの部分が処理されると、softwares_controller.rbのlistメソッドが呼び出される。よって、付加情報を取り出す処理はlistメソッドに書く。

コントローラ softwares_controller.rbのlist
@keyword_id = params[:keyword_id]
  • paramsを使うと、指定したキー、この例ではkeyword_idの付加情報を取り出すことが出来る。
  • ここでは@keyword_idという変数に1を代入していることになる。(わざわざインスタンス変数に代入したのは、このあとlist.rhtmlでこの値を利用したいから。)

取り出した付加情報で、表示する情報を絞り込む。

今までは、paginate :softwares, :per_page => 10によって、softwaresテーブルの全ての情報を取り出していた。
今回は、keyword_idフィールドが1のレコードだけ取り出したいので、オプションで:conditions => ["keyword_id = ?", @keyword_id]を追記した。

コントローラ softwares_controller.rbのlist
@software_pages, @softwares = paginate :softwares, :per_page => 10,
                                       :conditions => ["keyword_id = ?", @keyword_id]

:conditionsでSQL文を指定できる。["keyword_id = ?", @keyword_id]によって、keyword_idフィールドが変数@keyword_idと等しいものだけ抽出することになる。

      • Ruby風に"keyword_id = #{@keyword_id}"と書きたくなるのだが、不正アクセスの防止のためには["keyword_id = ?", @keyword_id]と書くべきとのこと。?に@keyword_idの値が代入されるのだが、その時SQLとして特別な意味を持つ文字を無視してくれるようだ。

全件表示に戻るリンクを作成する。

今は、キーワードに絞り込んだ後、全件表示に戻る手段が無い。(アドレスバーのURL「?keyword_id=1」を削除して実行すれば全件表示されるのだが...。)そこで、「New software | Back」のように表示して、Backに全件表示に戻るリンクを設定することにした。list.rhtmlの最終行に以下の2行を追加した。

list.rhtml
<%= ' |' unless @keyword_id == nil %>
<%= link_to 'Back', :action => 'list', :id => nil unless @keyword_id == nil %>

unless @keyword_id == nilで、キーワードで絞り込んだときだけ表示される。
コントローラで変数@keyword_idに代入したのは、この条件判断で利用するため。(コントローラからビューに値を引き継ぐためには@で始まるインスタンス変数を利用する必要がある。)

全件表示の見直し

これでOKと思い、試してみる。キーワードをクリックすると、そのキーワードの行だけ表示された!こちらは成功。
次はBackをクリックして全件表示に戻ってみると...

なんと、1件も表示されない...。これじゃ0件表示だ。
コードを見直すとこれはすぐに解決。全件表示だとkeyword_idがnilになる。paginateのconditionsの条件が「keyword_id=nil」になってしまうため、正しく評価されないのだろう。そこで以下のようにコードを変更した。

コントローラ softwares_controller.rbのlist
  def list
    @keyword_id = params[:keyword_id]
    conditions = ["keyword_id = ?", @keyword_id] unless @keyword_id == nil
    @software_pages, @softwares = paginate :softwares, :per_page => 10,
                                           :conditions => conditions
  end
  • 絞り込みの検索条件を変数conditionsに代入して、paginateの検索条件は変数conditionsで指定するようにした。
  • 変数conditionsにはkeyword_idが指定されている時しか検索条件が代入されないので、全件表示の時は:conditions => nilという設定になる。
  • :conditions => ["keyword_id=nil"]と違って、:conditions => nilなら検索条件を指定しない扱い、つまり全件表示になる。

これで全件表示、キーワード絞り込みが自在にできるようになった!

全件表示
キーワードRuby on Railsで絞り込み