Rails:通过下拉列表和复选框过滤索引

时间:2011-09-24 15:55:18

标签: ruby-on-rails checkbox filter params

我正在尝试通过下拉菜单(位置)和一组复选框(类别)过滤产品的索引页面,而不是非常成功。我可以通过下拉列表来过滤任何位置或类别。我还可以在一个表单中组合两个下拉列表,但如果我无法获得两个单独表单的工作解决方案。

我想要实现的是提交onchange的位置的下拉列表以及我希望具有过滤器按钮的复选框的类别。

我目前的代码提供下拉列表和复选框,但存在一些问题:

  • 复选框列出了所有类别,但是当我根据这些类别进行过滤时,params作为数组传递但在视图中没有返回任何产品
  • 每当我按类别过滤时,我都会失去先前的位置选择

以下是相关代码:

产品型号

....
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :localizations
has_many :locations, :through => :localizations
class Product < ActiveRecord::Base
default_scope :order => 'end_date'
scope :not_expired, where('end_date > ?', Time.now)
scope :location, lambda { |*location_id| {:include => :locations, :conditions => ["locations.id = ?", location_id]} }
scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["categories.id = ?", category_id]} }
scope :unique, :group => "title"

控制器

class LibraryController < ApplicationController
  def index
    if params[:location_id] && params[:category_ids]
    @products = Product.not_expired.unique.location(params[:location_id]).category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:category_ids]
    @products = Product.not_expired.unique.category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
    elsif params[:location_id]
    @products = Product.not_expired.unique.location(params[:location_id]).paginate(:page => params[:page], :per_page => 9)
    else
    @products = Product.not_expired.unique.paginate(:page => params[:page], :per_page => 9)
    end
  end
end

图书馆index.html.erb

<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>

      <div class="filter_options">

        <form class="filter_locations", method="get">
          <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
          <%= select_tag "location_id", options_for_select(@options), :onchange => "this.form.submit();", :include_blank => true %> 
        </form>

        <form class="filter_categories", method="get">
          <% for category in Category.all %>
            <%= check_box_tag("[category_ids][]", category.id) %>
            <%= category.name %>
          <% end %>
          <input type="submit" value="Filter" />
        </form>
    </div>

我一直围着这个圈子走,所以任何方向都非常感谢。

部分回答我自己的问题我修改了库索引并在类别表单中使用了一个隐藏字段,该字段调用了location_id param(如果存在),这意味着我可以保留选择类别后所做的任何位置选择复选框。

进一步更新我已经添加了一个检查类别复选框是否通过查询params,更新库index.html.erb来检查。

包含@rdvdijk输入的最后编辑(谢谢)

library index.html.erb

.......
    <%= form_tag( '', :method => :get ) do %>
      <% @options = Location.all.map { |a| [ a.name, a.id ] } %>
      <%= select_tag "location_id", options_for_select((@options), params[:location_id]), :onchange => "this.form.submit();", :include_blank => true %> 
    <% end %>
    <%= form_tag( '', :method => :get ) do %>
      <% if(params.has_key?(:location_id)) %>
        <%= hidden_field_tag 'location_id', params[:location_id] %> 
      <% end %>
    <% Category.all.each do |category| %>
    <%= check_box_tag 'category_ids[]', category.id, params[:category_ids].to_s.include?(category.id_to_s) %>
      <%= category.name %>
    <% end %>
    <%= submit_tag 'Filter' %>
    <% end %>
.......

2 个答案:

答案 0 :(得分:1)

您有两种形式,我认为这是您问题的一部分。每当您更改第一个表单中的位置时,只会将location_id发送到您的控制器index操作。每当您选择一个类别并提交第二个表单时,只有category_ids会被发送到您的控制器index操作。

使用一个表单,看看会发生什么。至少应该使过滤适用于单个提交。

我看到的第二个问题是您没有选择所选位置,或检查所选类别。

请查看options_for_selectcheck_box_tag的文档以解决此问题。

答案 1 :(得分:0)

在我的情况下,产品belongs_to:类别和类别has_many:产品,我修改了categories.id到category_id,它有效!

scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["category_id = ?", category_id]} }