hard time with checkboxes

Hi, I've been having a heck of a time trying to get checkboxes for filter options of a search page working. I have a SearchController and views: index, keyword, for the searching part. And I have the Event model, controller and views. The Event model contains the actual search method since I need to search through all Events for the given keyword. What I need to do is somehow get the Event model to know whether or not the checkboxes in the Search view index are checked without using a database. I tried using attr_reader, but it doesn't work. This is what I have now:

class Event < ActiveRecord::Base

attr_accessor :search_streams attr_accessor :search_auds

def self.search(keywords, options = {}, *args)

    if @search_streams == "1"        ...     end

    if @search_auds == "1"        ...     end

end

class SearchController < ApplicationController def index    @calendars = Calendar.find(:all)    @calendars << default_calendar end

And in the search index view:

<p class="help">Find events that interest you.</p>

<% form_for :event do |f| %>   <%= f.check_box :search_streams, {:class => 'check'} %>&nbsp; Search Streams <br />   <%= f.check_box :search_auds, {:class => 'check'} %> &nbsp; Search Audiences <br /> <% end %>

Is it even possible to access the checkboxes from the search index in the Event model? I really need help with this, I'm so confused about checkboxes... I'm not even sure of how to get whether or not checkboxes are even checked!

hi again,

ok, there are some misunderstandings: attr_accessor would allow to generate a kind of virtual attribute for an object of event. Since you don't have one but want to work on the class level, forget about it for now

check your development.log file for the params you get when submitting the form.

there should be something like params[:event][:search_streams]

and it should have a value "0" or "1"

to get them into your search method, just add two params:

def self.search(search_streams, search_auds, keywords, options = {}, *args)

call it with Event.search(params[:event][:search_streams], params[:event][:search_auds], ...)

by the way: since you checkboxes have (technically) nothing to do with event objects, there is no real need to use form_for, a simple form_tag would to (like proposed yesterday)

few details to forms in general, checkboxes in special & the params hash.

1) Whatever you submit from a form will end in your params hash   - this can be accessed in the controller or the view   - not directly in the model (you can hand it as a methods attribute of course) the name is always the same as that of the form element. so if your checkbox name is "search_streams" you'll find it's value in params[:search_streams]. This value is always a string. For checkboxes that's a "1" (checked) or "0" (unchecked). These values can be configured:

check_box("puppy", "gooddog", {}, "yes", "no")

in this case the return value would be "yes" or "no" in params[:puppy][:gooddog] But there is no real need to do this in most cases.

The most simple checkbox:

check_box_tag 'accept'

would return "1" or "0" in params[:accept] You would use this with form_tag.

If you use form_for Rails will add the object class to the name:

form_for :puppy do |f|   f.checkbox :gooddog end

will give you params[:puppy][:gooddog]

If in any case you're unsure, how or what your submit returns, look in the output in development.log or in the terminal output of your server. You'll find a line like this:

Processing LoginsController#edit (for 127.0.0.1 at 2008-05-30 13:47:19) [GET]   Session ID: 6601a5bbfa26e7d60967710c49a1203720462a22...   Parameters: {"action"=>"edit", "event"=>{"search_streams"=>"1", "search_aud"=>"0"}, "controller"=>"admin/logins"}

You can see the splitted params for event and it's content, the two values of your checkbox.

Thorsten Mueller wrote:

check your development.log file for the params you get when submitting the form.

there should be something like params[:event][:search_streams]

and it should have a value "0" or "1"

I'm not seeing anything like this in the log...I just see:

Processing SearchController#index (for 127.0.0.1 at 2008-05-30 09:00:53) [GET]   Session ID: 47bf040683602f74418e9857e941df1a   Parameters: {"action"=>"index", "controller"=>"search"}

by the way: since you checkboxes have (technically) nothing to do with event objects, there is no real need to use form_for, a simple form_tag would to (like proposed yesterday)

So I would use <%= check_box_tag("Search Streams", "event[search_streams]") %>? How do I use this with form_tag?

Thanks so much for helping me again, I didn't think I explained my problem very well in the last thread so I tried to give a better outline of it here.

Are the checkboxes even being submitted? lol:

<% form_for :event do |f| %>   <%= f.check_box :search_streams, {:class => 'check'} %>&nbsp; Search Streams <br />   <%= f.check_box :search_auds, {:class => 'check'} %> &nbsp; Search Audiences <br /> <% end %>

<% form_tag({:controller => 'search', :action => 'keyword'}, {:method => 'post'}) do -%>   <%= text_field_tag 'text' -%> <%= submit_tag 'Search' -%> <br /> <br />

It looks to me like I have 2 separate forms going on (yay for not knowing what I'm doing!)..... if I used the check_box_tag way instead, could I place them inside the form_tag and have the 'Search' submit_tag submit the checkboxes?

ok, I think it's best, first to get your form data as params into the controller and later see, how to use it for search within the model.

I'm not seeing anything like this in the log...I just see:

...

that helps :slight_smile:

your form:

<% form_for :event do |f| %>   <%= f.check_box :search_streams, {:class => 'check'} %>&nbsp; Search Streams <br />   <%= f.check_box :search_auds, {:class => 'check'} %> &nbsp; Search Audiences <br /> <% end %>

does not have a submit button. So you get to the controller via a link? Then you'll never get any params from the form.

The most simple form. Since it's not providing any attributes for event a such, I'll use the form_tag:

<% form_tag(:controller => "search, :action => "index") do %>   <%= check_box_tag(:search_streams) %>Search Streams <br />   <%= check_box_tag(:search_auds) %>Search Audiences <br />   <%= submit_tag('Search') %> <% end %>

This should give you the params in the simple form params[:search_streams] (and show up in development.log)

Thorsten Mueller wrote:

The most simple form. Since it's not providing any attributes for event a such, I'll use the form_tag:

<% form_tag(:controller => "search, :action => "index") do %>   <%= check_box_tag(:search_streams) %>Search Streams <br />   <%= check_box_tag(:search_auds) %>Search Audiences <br />   <%= submit_tag('Search') %> <% end %>

This should give you the params in the simple form params[:search_streams] (and show up in development.log)

Okay I now have

<% form_tag(:controller => 'search', :action => 'index') do %>   <%= check_box_tag(:search_streams) %>Search Streams <br />   <%= check_box_tag(:search_auds) %>Search Audiences   <%= submit_tag('Save Changes') %><br /><br /> <% end %>

<% form_tag({:controller => 'search', :action => 'keyword'}, {:method => 'post'}) do -%>   <%= text_field_tag 'text' -%> <%= submit_tag 'Search' -%> <br /> <br /> <% end -%>

in my index...and also in my keyword view (shows the results), and I'm getting Parameters: {"commit"=>"Save Changes", "action"=>"index", "controller"=>"search", "search_auds"=>"1", "search_streams"=>"1"} in my log now like you said i should. But when I don't click one of the boxes, it doesn't put "search_auds" => "0" or anything... is this what's supposed to happen?

Also, would I be able to include the checkboxes with the text_field_tag so that the user doesn't have to submit their filter preferences separately from their actual search?

Okay so I did this:

<% form_tag({:controller => 'search', :action => 'keyword'}, {:method => 'post'}) do -%>   <%= check_box_tag(:search_streams) %>Search Streams <br />   <%= check_box_tag(:search_auds) %>Search Audiences <br /><br />   <%= text_field_tag 'text' -%>   <%= submit_tag 'Search' -%> <br /> <br />

<% end %>

I just put the checkboxes in the text_field's form (which is the same just with :method => post, and the action to go to keyword because the keyword page is the page that shows results for the search). Now I'm getting "#<ArgumentError: wrong number of arguments (2 for 3)>". What arguments is it talking about? I think it has to do with either the 'keyword' view or the ":method => 'post'" (what does that do anyway?)

Amanda .. wrote:

Is it even possible to access the checkboxes from the search index in the Event model? I really need help with this, I'm so confused about checkboxes... I'm not even sure of how to get whether or not checkboxes are even checked!

In my experience checkboxes can be a real pain since their submission appears to be browser-dependent. Generally, I've found that if a checkbox is checked, the name/value pair will be sent just as you'd expect with any form param. If the box is NOT checked, the item is not submitted at all. It's not submitted with a value of "", it's just not submitted. To do a test for checkbox state means your code needs to assume the checkbox was there on the page and test for its presence in the form parameter list. If it's absent from your list, then the checkbox wasn't checked.

I made a quick little page that illustrates this using a simple <form action="get"> so you can see what happens in your URL bar:

http://railsdotnext.com/checkboxtest.shtml

- Aaron

Thorsten Mueller wrote:

This would depend on which line generates this error. (Is it when you render the view or after submit in the controller?)

if it's the line with the form_tag, then try this:

<% form_tag(:controller => 'search', :action => 'keyword') do -%> or <% form_tag(:controller => 'search', :action => 'keyword', :method => :post) do -%>

It happens when I try to submit the form

It happens when I try to submit the form

ok, then the view code for the form is ok (should be, since none of the used functions requires 3 arguments.

The error message should tell you, in which line the error happen.

Or just post the code of the keywords action.

SearchController

def keyword     params[:search_auds] = "0"     params[:search_streams] = "0"     params[:text]=clean_input(params[:text]) unless params[:text].blank?

    @events = Event.search params[:search_streams, :search_auds, :text], {"calendars" => @calendars, :status => :approved, :include_expired => false, :order => @order, :limit => @limit}     @event_pages = Paginator.new self, @events.size, 15, params[:page]     @user_events = @events[@event_pages.current.offset..@event_pages.current.offset+@event_pages.items_per_page]   end

thats the part that it says is the problem, I just added the :search_streams, :search_auds parameters to Event.search...I thought that would fix the problem but now it's telling me theres a wrong number of arguments (3 for 1) instead of 2 for 3

maybe it could be happening in the switch from the 'index' view to the 'keyword' view?

keyword view:

<% form_tag(:controller => 'search', :action => 'keyword', :method => 'post') do -%>   <%= check_box_tag(:search_streams) %>Search Streams <br />     <%= check_box_tag(:search_auds) %>Search Audiences <br />   <%= text_field_tag 'text' -%>   <%= submit_tag 'Search' -%> <br /> <br /> <% end -%> <br />

<% if @events.any? %>

<div class="vcalendar">

<p class="navigation-hint">Events containing '<%= params[:text] %>':</p>

<ul class="timeline"> <% for event in @user_events %>   <% if !event.hidden? || (event.hidden? && event.admin_by?(current_user))%>   <li class="vevent">     <%= render :partial => 'calendar/edit', :locals => {:event => event} %>

        <h3 class="summary"> <%= textilize_without_paragraph(event.title) %> </h3>

        <%= render :partial => 'calendar/event_permalink', :locals => {:event => event} %>

        <%= render :partial => 'calendar/event_top', :locals => {:event => event} %>

        <%= render :partial => 'calendar/event_bottom', :locals => {:event => event} %>

        <% if signedIn? %>         <%= render :partial => 'calendar/event_options', :locals => {:event => event} %>         <% end %>

        <%= render :partial => 'calendar/event_all_occurrences', :locals => {:event => event} %>

    </li>     <% end %> <% end %> </ul>

<% unless @event_pages.length <= 1 %>

<p class="help"><%= pagination_links(@event_pages, :window_size => 4, :params => params) %></p> <% end %> </div>

<% else %> <p>No events found. Try another search.</p>

I think it might be from not getting the values from the checkboxes on the index view to the keyword view?

<% end %>

Scratch that problem, I fixed it...silly me, I put

    @events = Event.search params[:search_streams, :search_auds, :text], ...

when I should've had:

    @events = Event.search params[:search_streams], params[:search_auds], params[:text], ...

thats the part that it says is the problem, I just added the :search_streams, :search_auds parameters to Event.search...I thought that would fix the problem but now it's telling me theres a wrong number of arguments (3 for 1) instead of 2 for 3

the 3 for 1 error comes from that code

params[:search_streams, :search_auds, :text]

it's a hash, you can't use it that way.

do you still have: def self.search(keywords, options = {}, *args)

or did you change it?

@events = Event.search params[:search_streams, :search_auds, :text], ... should @events = Event.search [params[:search_streams], params[:search_auds], params[:text]], ...

then in search the argument keywords would be an array, containing those three values (not the way I would do it...

def self.search(keywords, search_streams, search_auds, options = {}, *args)

and call with @events = Event.search params[:text],params[:search_streams], params[:search_auds], ...

should work

And it looks as if everything's working properly now!

Thanks so much for you help, I really appreciate it!! Hopefully I can handle this from here on out :slight_smile:

oh, and I had changed the search to:

def self.search(search_streams, search_auds, keywords, options = {}, *args)

as you suggested before :slight_smile: