Chapter 11 - Searching and browsing
Introduction
In principle, our alphabetical community index lets any user find any other user, but using it in this way would be terribly cumbersome. In this chapter, we add more convenient and powerful ways to find users. We begin by adding full-text search to RailsSpace by making use of an open-source project called Ferret. We then stalker-enable our site with browsing by age, sex, and location.
Adding search and browse capability to RailsSpace will involve the creation of custom
pagination and validations, which means that we will start to rely less on the built-in
Rails functions. This chapter also contains a surprising amount of geography, some fairly
fancy finds, and even a little math.
Table of Contents
- 11.1 Searching 327
- 11.1.1 Search views 328
- 11.1.2 Ferret 330
- 11.1.3 Searching with find_by_contents 332
- 11.1.4 Adding pagination to search 336
- 11.1.5 An exception to the rule 339
- 11.2 Testing search 341
- 11.3 Beginning browsing 343
- 11.3.1 The browse page 343
- 11.3.2 Find by A/S/L (hold the L) 345
- 11.4 Location, location, location 350
- 11.4.1 A local database of geographical data 351
- 11.4.2 Using GeoData for location search 352
- 11.4.3 Location names 355
- 11.4.4 Adding browse validation 358
- 11.4.5 The final community home page 363
Source Code
- Listing 11.1 app/views/community/_search_form.rthml
- Listing 11.2 app/views/community/search.rthml
- Listing 11.3 app/views/community/index.rhtml
- Listing 11.4 app/models/spec.rb
- Listing 11.5 app/models/faq.rb
- Listing 11.6 app/models/user.rb
- Listing 11.7 app/controllers/community_controller.rb
- Listing 11.8 app/controllers/community_controller.rb
- Listing 11.9 app/controllers/community_controller.rb
- Listing 11.10 app/controllers/application.rb
- Listing 11.11 app/views/community/_user_table.rhtml
- Listing 11.12 app/controllers/community_controller.rb
- Listing 11.13 app/views/community/search.rhtml
- Listing 11.14 test/fixtures/users.yml
- Listing 11.15 test/fixtures/users.yml
- Listing 11.16 test/functional/community_controller_test.rb
- Listing 11.17 app/controllers/community_controller.rb
- Listing 11.18 app/views/community/browse.rhtml
- Listing 11.19 app/views/community/_browse_form.rhtml
- Listing 11.20 app/controllers/community_controller.rb
- Listing 11.21 app/models/spec.rb
- Listing 11.22 db/migrate/007_create_geo_data.rb
- Listing 11.23 app/models/geo_datum.rb
- Listing 11.24 app/models/spec.rb
- Listing 11.25 app/models/spec.rb
- Listing 11.26 lib/string.rb
- Listing 11.27 app/models/spec.rb
- Listing 11.28 lib/object.rb
- Listing 11.29 app/helpers/application_helper.rb
- Listing 11.30 app/controllers/community_controller.rb
- Listing 11.31 app/controllers/community_controller.rb
- Listing 11.32 app/views/community/browse.rhtml
- Listing 11.33 app/views/community/index.rhtml
GeoData
The canonical place to get the data is from populardata.com but we also provide a copy, one that worked on Mac and Linux, and a second that we edited for Windows:- geo_data.csv - Mac/Linux
- geo_data_alternate.csv - Windows
Errata
As of the first printing, these are the known corrections:
- p. 331. The command line to install the Ferret plugin spans two lines and it's not clear that it's not supposed to. The full line is:
ruby script/plugin install svn://projects.jkraemer.net/acts_as_ferret/tags/stable/acts_as_ferret - p. 334. Listing 11.8 is missing an end after
@users = @users.sort_by { |user| user.spec.last_name }:
def search @title = "Search RailsSpace" if params[:q] query = params[:q] # First find the user hits... @users = User.find_by_contents(query, :limit => :all) # ...then the subhits. specs = Spec.find_by_contents(query, :limit => :all) faqs = Faq.find_by_contents(query, :limit => :all) # Now combine into one list of distinct users sorted by last name. hits = specs + faqs @users.concat(hits.collect { |hit| hit.user }).uniq! # Sort by last name (requires a spec for each user). @users.each { |user| user.spec ||= Spec.new } @users = @users.sort_by { |user| user.spec.last_name } end end - p. 339. Section 11.1.5 - Depending on which version of Ferret you have installed, you may not get an error at all when searching for "--". They fixed this bug but it is still a good idea to handle exceptions.
- p. 342. Listing 11.16 should be titled test/functional/community_controller_test.rb
- Some listings are titled app/views/controllers/community_controller.rb but should be app/controllers/community_controller.rb
- p. 344. Listing 11.17
- p. 345. Listing 11.20
- p. 361. Listing 11.30
- p. 361. Listing 11.31
- p. 343. The test code given in Listing 11.16 requires the creation of the
YAML file in
test/fixtures/geo_data.ymlwith some contents like:Caltech: id: 1 zip_code: 91125 latitude: 33.7866 longitude: -118.299 city: PASADENA state: CA county: LOS ANGELES type: - p. 349. All occurrences of "find_by_sql" should be "find_by_asl".