Filtering a Database

Hey there,

In my rails app, I need to filter a database and print the results.
Initially, when you load the web page, all the results are listed in
all their non filtered glory. So what I've done is added a button and
a drop down list. The list holds the types by which you'd like to
filter, and the button starts the filter (in theory).

The problem is... I'm not sure how to do the filter. Queries sound
like they would be the best bet. I could call a query based on the
filter type and print the results. But where would I query? In a
controller? A query would need to be done every time the filter button
was pressed. Is it possible to ask for a query in the rhtml code?

Since I honestly didn't know, I tried another approach. I defined a
ruby method in the rhtml:

<!-- Ruby organize method for filter -->
<% def organize ( f_type ) %>

  <% @clients.each do |client| %>

  <-- a bunch of code here -->
<% end %>

And after I was on the verge of success, I got an error:

undefined local variable or method `_erbout' for #<#<Class:0x438701c>:
0x4386ff4>

I did some research and what I gathered is that I'm a horrible person
for trying to define a ruby method in the rhtml. I thought about
defining the method in a controller, but the method includes html code
in order to print out the filtered list. So that wouldn't work. Now
I'm stumped. Should I use queries? If so, how would I? Or am I wrong
about _erbout and take the method approach?

I have one other question. Lets say I want to do something based on
the value picked in a drop down list (like... filter!). Is there a
variable that stores the picked drop down list value so that I can use
it in a conditional?

Thanks for your help,
Brad

ok, lets sort that out:

1) yes, you want to do that in a controller

say you have an index action, then do some searching like:

@clients = Client.find(:all, :conditions => "whatever you search for")

the results you use in your code like you started to do:

<% @clients.each do |client| %>
...
<% end %>

without any method definitions
There should never be any complex logic in the view

getting the params from your view to the controller:

- define a form
- put the dropdown list in that form
- have a submit button submit that form to your index action
then again let your index action perform search based on
the content of the dropdown list which you'll find in the params hash
params[:name_of_dropdown]

Pardon my inexperience. I'm not sure what you mean by index action,
but I assume its the action of the button being pressed. So in my
controller I have...

@filter_mso = RemoteSite.find('name', 'vodsystem_id', 'ip',
'oiversion_id', 'idgversion_id', 'oidir', 'idgdir', 'client_id',
'region_id', 'comments', 'bmssystem_id', 'oi_status_id',
'idg_status_id', 'stb_id', :conditions => 'client_id = 1', :order =>
'name asc')

Now the problem I have is how to initiate this. What do I put after
onclick: so that I use these results to filter and print out? I doubt
I put all the code immediately after onclick:, which is why I had
methods on my mind. I can type onclick: method_name and it will run
all the code contained in the method.

"getting the params from your view to the controller:

- define a form
- put the dropdown list in that form
- have a submit button submit that form to your index action
then again let your index action perform search based on
the content of the dropdown list which you'll find in the params hash
params[:name_of_dropdown]"

You lost me there.

Pardon my inexperience. I'm not sure what you mean by index action,
but I assume its the action of the button being pressed.

This is an action in REST design, used for displaying a list
of this resource. If you have a resource like a Client REST
would define:

index: list all (or a selection of) clients
new: display a form for a new client
create: take the new form data & create a new client
edit: display aform to edit an existing client
update: take the edit form data & update a client
destroy: delete a client

But that's only a question of code design many people use
and you don't need to worry about it for now too much.
You can give this action any name you want.

So in my

controller I have...

@filter_mso = RemoteSite.find('name', 'vodsystem_id', 'ip',
'oiversion_id', 'idgversion_id', 'oidir', 'idgdir', 'client_id',
'region_id', 'comments', 'bmssystem_id', 'oi_status_id',
'idg_status_id', 'stb_id', :conditions => 'client_id = 1', :order =>
'name asc')

Now the problem I have is how to initiate this. What do I put after
onclick: so that I use these results to filter and print out? I doubt
I put all the code immediately after onclick:, which is why I had
methods on my mind. I can type onclick: method_name and it will run
all the code contained in the method.

Ok. Please excuse, if I tell you stuff you know, but from your post
I assume, that you got an important point wrong.
Even if you could define a ruby method as you did in your first post,
you can never call it from javascript.
Ruby & Rails on the server
JavaScript runs on the browser

So what you have todo is post the selection from the braowser to
an action on the server, which will take this param, run a search on
the db
and render the result back to the browser.

"getting the params from your view to the controller:

- define a form
- put the dropdown list in that form
- have a submit button submit that form to your index action
then again let your index action perform search based on
the content of the dropdown list which you'll find in the params hash
params[:name_of_dropdown]"

So lets sort that out.
Problem: There are many ways to do this. Thanks to Ajax
you can in fact have a javascript function in the onclick event
be smart enough, to post data without having a form.
But it's slightly more complicated than the simple form and I
think you should start with that:

first that query:
@filter_mso = RemoteSite.find('name', 'vodsystem_id', 'ip',
'oiversion_id', 'idgversion_id', 'oidir', 'idgdir', 'client_id',
'region_id', 'comments', 'bmssystem_id', 'oi_status_id',
'idg_status_id', 'stb_id', :conditions => 'client_id = 1', :order =>
'name asc')
Why do you list all the field names?

@filter_mso = RemoteSite.find(:all, :conditions => 'client_id =
1', :order => 'name asc')
is all you need (and from a rails point of view, that's weak code and
could still be enhanced,
using the associations between client & remotesite models

Now have a form with your dropdown (assuming the controller is named
clients_controller & the action list_remote_sites)
<% form_tag('/list_remote_sites') do -%>
  <%= select_tag("search_options", "<option>something</

", :onclick => "this.form.submit();") %>

<% end -%>

This way in your controller you'll get the result in
params[:search_options]
Based on this you can make your search and render the new page
with it's search results.

Thanks a lot for all your help. Sadly this is all still foreign to me
so I'm still struggling. First, what is an action?

Now have a form with your dropdown (assuming the controller is named
clients_controller & the action list_remote_sites)
<% form_tag('/list_remote_sites') do -%>
  <%= select_tag("search_options", "<option>something</
>", :onclick => "this.form.submit();") %>
<% end -%>

This way in your controller you'll get the result in
params[:search_options]
Based on this you can make your search and render the new page
with it's search results.

Here is my dropdown, with the button and a second list to further
define whats being filtered:

<!-- Filter -->
<tr>
    <td class="option"> (here's the button,
still not sure what to put after onclick: so that once the query is
made it starts printing the filtered objects)
        <input style="font-size: 12pt; font-weight:bold" type="button"
onclick=??? value="Filter" />
        by:
        <td
class="option">
(first drop down list, determines filter category)
         <select name="filter_list[name]">
             <% @filter_lists.each do |filter_list| %>
              <option value="<%= filter_list.id %>"
                <%= ' selected' if filter_list.id == @filter_lists.id
%>>
                <%= filter_list.name %>
                </option>
                <% end %>
            </select>
       </td>

       <% #if ( name == 'MSO' ) %> (My attempt
earlier to decide on what would show up in this list based on what was
picked in the first (category) list)
</tr>
</table>
<tr>
    <td
class="option>
(second drop down, determines which item within category)
  MSO name:
  <td class="option">
         <select name="remote_site[client_id]">
             <% @clients.each do |client| %>
            <option value="<%= client.id %>"
                    <%= ' selected' if client.id == @clients.id %>>
                    <%= client.name %>
                </option>
                <% end %>
            </select>
       </td>
</tr>

Now I have no idea what a form is. But from what I've gathered from
what you've said, I need to create one within the dropdown, to get
something like this:
(controller is named RemoteSiteController, don't know what the action
is)

<!-- Filter -->
<tr>
    <td class="option">
        <input style="font-size: 12pt; font-weight:bold" type="button"
onclick=??? value="Filter" />
        by:
        <td class="option">
        <% form_tag('/action_name') do -%>
          <%= select_tag("search_options", "<option>filter = 'MSO'</

, :onclick => "this.form.submit();") %>

        <% end %>
         <select name="filter_list[name]">
             <% @filter_lists.each do |filter_list| %>
              <option value="<%= filter_list.id %>"
                <%= ' selected' if filter_list.id == @filter_lists.id
%>>
                <%= filter_list.name %>
                </option>
                <% end %>
            </select>
       </td>

       <% #if ( name == 'MSO' ) %>
</tr>
</table>
<tr>
    <td class="option>
  MSO name:
  <td class="option">
         <select name="remote_site[client_id]">
             <% @clients.each do |client| %>
            <option value="<%= client.id %>"
                    <%= ' selected' if client.id == @clients.id %>>
                    <%= client.name %>
                </option>
                <% end %>
            </select>
       </td>
</tr>

So with that, I could make an instance variable, like @mso_filter =
@param[:search_options]
So @mso_filter would have the parameter value. And... within my query
I use @mso_filter as part of my search?

@filter_mso = RemoteSite.find(:all, :conditions => 'client_id =
@mso_filter', :order => 'name asc, ip asc')

Once I have my query I use it in the rhtml somewhere that will print
out once the button is clicked.
How much did I screw up?