Filtering records using a <select> control

I have recently been working on a simple list action and view that will allow a user to filter the objects that are selected by changing a category value in a <select> control.

In this case, the resources being listed are restaurants. The view also contains a list of all restaurant categories, which defaults to a selection of "All Categories", that will allow them to filter the restaurants displayed by category.

I have a working implementation, however, it feels like a bit of a hack. In the view, I am using the form_for and collection_select helpers, because they handle auto-selecting the appropriate value and don't require me to assemble an options hash. The part that feels like a hack to me is that in order to get the auto-selection to work, I am creating a Category model object in the controller, and assigning the id value that was submitted through the form as the object's "id" property. Also, I have to explicitly set the "name" property in the htmlOptions hash, so that the field gets submitted as params[:category_id] rather than params[:category_id].

I am new to Rails, and I wanted to see if anyone felt there was a cleaner way for me to implement this functionality. Anyhow, here's the code. Any suggestions would be greatly appreciated:

#** Controller **# def index     (@category = Category.new()).id = params[:category_id]

    if (!@category.id.nil?)       @restaurants = Restaurant.find_all_by_category_id(@category.id)     else       @restaurants = Restaurant.find(:all)     end

    respond_to do |format|       format.html { @categories = Category.find(:all) } # index.html.erb       format.xml { render :xml => @restaurants }     end end

#** View (index.rhtml) **# <% form_for( :category, :html => {:method => :get}) do |f| %>     <%=         f.collection_select(             :id,             @categories,             :id,             :name,             {:include_blank => 'All Categories'},             {:onchange => 'this.form.submit();', :name => 'category_id'}         )     %> <% end %>

Lastly, I was wondering if it would it make more sense to move the category selection form to a partial, rather than embed it directly in index.rhtml with these rest of the code (which is not shown above)?

Thanks for the help,

Justin Holzer

Justin Holzer wrote:

I have recently been working on a simple list action and view that will allow a user to filter the objects that are selected by changing a category value in a <select> control.

In this case, the resources being listed are restaurants. The view also contains a list of all restaurant categories, which defaults to a selection of "All Categories", that will allow them to filter the restaurants displayed by category.

I have a working implementation, however, it feels like a bit of a hack. In the view, I am using the form_for and collection_select helpers, because they handle auto-selecting the appropriate value and don't require me to assemble an options hash. The part that feels like a hack to me is that in order to get the auto-selection to work, I am creating a Category model object in the controller, and assigning the id value that was submitted through the form as the object's "id" property. Also, I have to explicitly set the "name" property in the htmlOptions hash, so that the field gets submitted as params[:category_id] rather than params[:category_id].

I am new to Rails, and I wanted to see if anyone felt there was a cleaner way for me to implement this functionality. Anyhow, here's the code. Any suggestions would be greatly appreciated:

#** Controller **# def index     (@category = Category.new()).id = params[:category_id]

    if (!@category.id.nil?)       @restaurants = Restaurant.find_all_by_category_id(@category.id)     else       @restaurants = Restaurant.find(:all)     end

    respond_to do |format|       format.html { @categories = Category.find(:all) } # index.html.erb       format.xml { render :xml => @restaurants }     end end

#** View (index.rhtml) **# <% form_for( :category, :html => {:method => :get}) do |f| %>     <%=         f.collection_select(             :id,             @categories,             :id,             :name,             {:include_blank => 'All Categories'},             {:onchange => 'this.form.submit();', :name => 'category_id'}         )     %> <% end %>

<% form_tag do %> <%= select_tag :category_id,                 options_from_collection_for_select(                   @categories,                   :id,                   :name,                   params[:category_id]) %> <% end %>

Lastly, I was wondering if it would it make more sense to move the category selection form to a partial, rather than embed it directly in index.rhtml with these rest of the code (which is not shown above)?

Only if you reuse it elsewhere.