I am trying to learn rails from zero programming experience and have an app im trying to make. With much help from people on here, I have an index page of venues which are filterable by which area they belong to via a dropdown menu. I would like to be able to have the same affect but using checkboxes and also being able to select multiple areas to add to the filter. This is what I have so far:
Model :
class Venue < ActiveRecord::Base
belongs_to :user
has_many :reviews
belongs_to :area
scope :north, where(:area_id => "2")
scope :west, where(:area_id => "3")
scope :south, where(:area_id => "4")
end
Controller:
def index
if (params[:area] && Area.all.collect(&:name).include?(params[:area][:name]))
@venues = Venue.send(params[:area][:name].downcase)
else
@venues = Venue.all
end
end
Venues index.html.erb:
<div class="filter_options_container">
<form class="filter_form", method="get">
<%= select("area", "name", Area.all.collect(&:name), {:prompt => 'All Areas'}) %><br>
<input type="submit" value="Filter" />
</form>
<br><br>
<form class="filter_form", method="get">
<% Area.find(:all).each do |a| %>
<%= check_box_tag("area", "name") %>
<%= a.name %>
<% end %>
<input type="submit" value="Filter" />
</form>
</div>
<div class="venue_partials_container">
<%= render :partial => 'venue', :collection => @venues %>
<div class="clearall"></div>
<%= link_to 'add a new venue', new_venue_path, :class => "add_new_venue_button" %>
</div>
The first form (the dropdowns) in the filter_options_container works fine but the checkboxes (the second form) is returning "can't convert Symbol into Integer" what am I missing/doing wrong?
Thankyou for any help.
I don't know exactly what's causing your error, but I can tell you that the check_box_tag
helper isn't working the way you expect it to. From the documentation, it's defined like this:
check_box_tag(name, value = "1", checked = false, options = {})
So calling check_box_tag("area", "name")
repeatedly will just give you <input id="area" name="area" type="checkbox" value="name" />
multiple times. Note that the "value" attribute (which is the value that gets sent to your server when that form is submitted) is always "name" - not what you want!
Instead, try the following:
<% Area.all.each do |a| %>
<%= check_box_tag("areas[]", a.id) %>
<%=h a.name %>
<% end %>
The things I've changed:
- I used
Area.all
instead of Area.find(:all)
- I did it for cosmetic reasons, but DanneManne's answer claims it's obsolete in Rails 3 (I wouldn't know - I'm still on 2.3.8).
- I used the area's ID instead of its name in the value field; it's always good to look things up by ID if you can - IDs are integers, and compare faster than strings, and there'll always be an index on the id column in your database for extra-fast lookups.
- And last, but way most importantly I threw in
[]
after the input name. This lets Rails collect all the values submitted with this name into an array, rather than just taking the last one. See below:
Throwing the URL...
/whatever?a=3&a=17&a=12
...at a Rails app gives you the params hash...
{:a => 12}
...but the URL...
/whatever?a[]=3&a[]=17&a[]=12
...gives you what you want:
{:a => [3, 17, 12]}
And if you have an array of all the area_ids you're interested in, you can get all the venues that are in any of those areas in a one-liner (isn't Rails great?):
filtered_venues = Venue.all(:conditions => {:area_id => params[:areas]})
Just make sure you have a valid array of area ids before calling that finder - if you don't, your conditions hash will evaluate to {:area_id => nil}, and Rails'll find you all the venues that don't have an area_id - probably none, and definitely not what you want.
Hope this helps!
In your call to Area.find you supply the argument :all. This syntax is deprecated in Rails 3 which I assume you are using. All the previous usages of find(:all, ...) or find(:first, ...) etc can no longer be used. Instead you should be using it like you in the first form: Area.all(...)
As a side note, it also looks like the check_box_tag arguments might be wrong. I guess you should send a.name instead of "name".
Here is a modified form that I think works:
<form class="filter_form", method="get">
<% Area.all.each do |a| %>
<%= check_box_tag("area", a.name) %>
<%= a.name %>
<% end %>
<input type="submit" value="Filter" />
</form>