The first step in extending the system is to enable searching for people. This requires changes to a few parts of the system:
Person
model, retrieving an array of Person
instances from the database. As the search only uses the Person
model, the logical place to locate the action is in the controller, which manages the other actions for that model: PeopleController
. We'll call the action search
. Person
instances: app/views/people/index.rhtml
. Therefore, we can just reuse that template, with some minor modifications such as a different page title.Once this functionality is in place, we'll be able to search the people
table with a URL like this:
http://localhost:3000/people/search?term=James
We first need a search
action on the PeopleController
(in app/controllers/people_controller.rb)
. This is fairly similar to the index
action: it retrieves a set of records from the database using a paginator and displays them. As noted above, we can also use the same view template (index.rhtml) to output the HTML, but we'll have to explicitly call it inside the action (highlighted below) as the action name doesn't match the template name. Here's the action in full:
def search
@paginator, @people = paginate :person, :per_page => 10,
:select => 'id, last_name, first_name',
:order => 'last_name, first_name'
@page_title = "Search results (page #{@paginator.current.number})"
render :action => 'index'
end
Test this at http://localhost:3000/people/search?term=Jeff
(put anything you like at the end of the URL—it's not being used yet). You should see something very similar to the index page for PeopleController
, but with a different title (Search results...). This proves that the route, action, and template are all working together.
Next, we need to use the term
parameter passed in the URL to narrow the results. In Chapter 4 (Finding Records Matching Search Criteria), we saw how to use a :conditions
option to restrict the results returned by find
. We can also use a :conditions
option with the paginate
method to restrict by our search term (highlighted):
def search # Get the search term from the querystring and put # percentage signs round it so it can be used with a LIKE query term = "%#{params[:term]}%" @paginator, @people = paginate :person, :per_page => 10, :select => 'id, last_name, first_name', :order => 'last_name, first_name', :conditions => ['last_name LIKE :term or first_name LIKE :term OR notes LIKE :term OR keywords LIKE :term', {:term => term}] @page_title = "Search results (page #{@paginator.current.number})" render :action => 'index' end
The :conditions
option here uses an alternative syntax available for SQL templates: instead of a question mark in the query (as used in Chapter 4, Finding Records Matching Search Criteria), you can use named placeholders, prefixed with a colon character. Then, you can use a hash as the second element of the array (here, {:term => term})
to specify the values to insert into the placeholders. Here we're using a single value, which gets inserted into four places in the query. This is a neat shortcut, particularly when you need to put the same value into multiple places in the query.
Now, try doing a search for someone in your database. For example, if you have a person called "Jeff" in your database, try doing:
http://localhost:3010/people/search?term=jeff
As we used LIKE
in the query, the search is case-insensitive (at least, when using MySQL). Hopefully, the page should only show people matching your query, e.g.:
The last step is to add a search form. To keep things simple, we'll add it to the layout directly (app/views/layouts/application.rhtml), at the bottom of the menu:
<li><%= link_to 'Addresses', :controller => 'addresses' %></li>
</ul>
<p>Search people</p>
<% form_tag({:controller => 'people', :action => 'search'}, {:method => :get}) do -%>
<p><input type="text" name="term" size="8" value=""/><br/>
<%= submit_tag 'Go' %></p>
<% end -%>
</div>
As we haven't got a model instance we are working with here, form_for
(which we used in Chapter 5, e.g. in the section Creating a Person) isn't really applicable. The simpler form_tag
helper generates an HTML<form>
element, which doesn't need to reference a model. It's also possible to pass both URL options (the first argument) and HTML options (the second argument) to the helper, to customize its behavior: in this case, we set the method to GET, to pass the term
variable in the querystring.
18.118.12.50