QA@IT

Railsで前回の画面の検索条件を、次の画面へ保持するためには?

3733 PV

現在Rails3.2で開発しているのですが、検索条件をどのように保存したらよいかわからず、質問させていただきました。

具体的にこのQA@ITを例に説明させてただきます。

このサイトはindex画面において、
「全ての質問」、「未解決の質問」、「注目の質問」
という検索条件があります。

そして、「未解決の質問」タブをクリックすると、画面遷移した先で「未解決の質問」タブがアクティブになっています。

  • 自分の考えた方法

私はこのような機能を実現するために、以下の様な実装をしました。

1,

@seach_options = Hash.new

このような感じで、コントローラで検索オプションを保持するためのハッシュを定義しました。

2,

先に定義したハッシュに、コントローラで値を入れました。


##全ての質問が呼びだれたときに呼び出されるコントローラのメソッド
def index_allquestion
   @seach_options[:url] = "allquestion"
end

## 未解決
def index_unresolved
   @seach_options[:url] = "unresolved"
end

## 注目
def index_featured
   @seach_options[:url] = "featured"
end

3,
erb内部で保持した検索条件に基づいてViewを作成しました。

<ul class="filter nav nav-tabs">

<% if  @seach_options[:url] == "allquestion" %>
<li class="active">
<% else %>
<li class="">
<% end %>
    <a href="/">すべての質問</a>
</li>

<% if  @seach_options[:url] == "unresolved" %>
<li class="active">
<% else %>
<li class="">
<% end %>
    <a href="/q/unresolved">未解決の質問</a>
</li>

<% if  @seach_options[:url] == "featured" %>
<li class="active">
<% else %>
<li class="">
<% end %>
     <a href="/q/featured">注目の質問</a>
</li>
</ul>
  • 上記のコードの問題点

うまく表現できないのですが、このコードはかなり泥くさい感じがするように感じました。

例えば、allquestionがマジックコードになっており、controllerの時と違うときの値をViewで書いてしまうと、エラーが出ずにおかしなViewになります。
またliという一行を表示するために5行ものコードを書く必要性があり、似た様な書き方が散見し、DRYではありません。
他には、今後タグで検索した場合、キーワードで検索した場合等にも、このようなやり方をする必要性があると考えられる。
といった点です。

  • 質問

改めて質問なのですが、検索条件を保持する際にはどのようなやり方がベストなのでしょうか?
ご回答いただけると幸いです。

回答

タブごとに異なる部分を適当なデータ構造で持って、それをレンダリングする部分テンプレート、ヘルパーメソッドを作成するとメンテナンスしやすいかと思います。

# app/views/shared/_tabs.html.erb
<ul class="filter nav nav-tabs">
<% tabs.each do |name, tab| %>
  <% li_class = "active" if name == current_tab %>
  <%= content_tag "li", class: li_class do %>
    <%= link_to tab[:label], tab[:url] %>
  <% end %>
<% end %>
</ul>
# app/helpers/tab_helper.rb
# encoding: UTF-8
module TabHelper
  # タブを増やしたいときは、ここに追加
  TABS = {
    allquestion: {
      url: "/",
      label: "すべての質問"
    },
    unresolved: {
      url: "/q/unresolved",
      label: "未解決の質問"
    },
    featured: {
      url: "/q/featured",
      label: "注目の質問"
    }
  }

  def render_tabs(current_tab)
    # 適切なタブ名が指定されていなければエラー
    raise "Undefined tab name #{current_tab.inspect}" unless TABS.has_key?(current_tab)
    render partial: "shared/tabs", locals: {tabs: TABS, current_tab: current_tab}
  end
end

Controller で @current_tab = :unresolved として View で <%= render_tabs(@current_tab) %> としてもよいですし、テンプレートごとに <%= render_tabs(:unresolved) %> などと書けるなら、Controller を汚さずに済みます。

編集 履歴 (0)
  • お返事ありがとうございます。

    前画面のデータはハッシュに保持して、それを適切なテンプレで表示するということですね。
    その方法でいこうと思います。ありがとうございました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。