Před časem jsem slíbil napsat krátký kurz k živému vyhledávání. Vyhledávání v textech, které průběžně zobrazuje výsledky během psaní dotazu.
Připravte si:
- Ruby on rails
- gem ferret (gem install ferret)
- gem acts_as_ferret (gem install acts_as_ferret)
- plugin auto_complete (v kořenovém adresáři aplikace spustit: ruby script/plugin install auto_complete)
Jak budeme postupovat
- Vytvoříme prázdnou aplikaci - jednoduchou databázi knížek
- Přidáme možnost vyhledávat v textech
- Zprovozníme živé vyhledávání
-
- Vytvoříme dílčí formulář (partial) pro vyhledávání - tam se bude zadávat dotaz
- Vytvoříme dílčí panel (partial) pro výsledky - tam budou nabízeny mezivýsledky hledání
- Upravíme controller tak, aby reagoval na vyhledávací dílčí formulář
Vytvoření databáze knížek
Vytvoříme malou aplikaci pro správu knihovničky. Bude uchovávat seznamy knížek, umožní nám je vypisovat a aktualizovat a nabídne i živé vyhledávání.
Pojďme tedy vytvořit kostru aplikace:
# Vytvor aplikaci v Rails
rails books
# vytvor databazi knih
echo "create database books" | mysql -u root -p
cd books
Nyní nastavíme jméno a heslo do databáze v souboru app/config/database.yml.
development:
adapter: mysql
database: books
username: root
password: heslo
host: localhost
port: 3306
Dále vytvoříme kostru aplikace. V kořenovém adresáři aplikace spustíme:
ruby script/generate scaffold Book title:string abstract:text
Vytvoříme tabulku knih
Nastartujeme vývojový server
A teď namíříme prohlížeč na http://127.0.0.1:3000/books a pořídíme nějaká ukázková data.
Přidání možnosti vyhledávat v textech
Změníme app/models/book.rb tak, aby podporoval vyhledávání v textu
require "acts_as_ferret"
class Book < ActivoRecord::Base
acts_as_ferret
end
V konzoli si můžete ověřit, že vyhledávání je už opravdu povolené. Nastartujte konzolu příkazem ruby script/console a zadejte tam
Book.find_by_contents("kniha").
Mělo by to vrátit podobný seznam výsledků jako u nás:
=> #<ActsAsFerret::SearchResults:0x2540f54 @results=[#<Book id: 2, title:
"Kniha promen", abstract: "Kniha o knize", created_at: "2008-07-07 23:16:38",
updated_at: "2008-07-07 23:16:38">, #<Book id: 1, title: "Prvni kniha",
abstract: "Toto je ma prvni knizka", created_at: "2008-07-07 23:16:23",
updated_at: "2008-07-07 23:16:23">], @total_hits=2>
Vytvoření živého hledání
Nakonec vytvoříme živé vyhledávání.
Dílčí formulář pro vyhledávání
K zobrazení vyhledávacího formuláře se použije partial search_pane.
Vytvořte dílčí formulář (partial) _search_pane.html.erb v podadresáři app/views/books a dejte do něj jednoduchou značku. Tato značka generuje automatický doplňovač v Ajaxu, který volá metodu auto_complete_for_search_query standardního controlleru (v našem případě books)
<%= text_field_with_auto_complete :search, :query %>
Přidejte do šablony knihovny app/views/layouts/books.html.erb deklaraci include pro javascript a zobrazování dílčího formuláře.
Nezapomeňte, že include pro javascript musí být v hlavě (head) šablony.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>Books: <%= controller.action_name %></title>
<!-- TADY -->
<%= stylesheet_link_tag 'scaffold' %>
<%= javascript_include_tag :defaults %>
</head>
<body>
<!-- A TADY -->
<%= render :partial=>"books/search_pane" %>
<p style="color: green"><%= flash[:notice] %></p>
<%= yield %>
</body>
</html>
Vytvoření dílčího panelu pro výsledky
Dílčí panel search_results zformátuje výsledky vyhledávání v textu a „nabídne“ uživateli mezivýsledky. Vytvořte partial app/views/books/_search_results.html.erb a přidejte do něj formátovací kód:
<ul>
<% for book in @books %>
<li><%= link_to h(book.title), :controller=>"books", :action=>"show", :id=>book %></li>
<% end %>
</ul>
Úprava controlleru
Přidejte následující řádek na začátek souboru books_controller.
protect_from_forgery :only => [:create, :update, :destroy]
Vytvořte metodu controlleru, která bude hledat knížky
def auto_complete_for_search_query
@books = Book.find_by_contents(params["search"]["query"]+"*", {:limit => 5})
render :partial => "search_results"
end
Nechceme generovat kompletně sesazenou stránku, což musíme upřesnit v controlleru books:
layout 'books', :except => [:auto_complete_for_search_query]
Tak, a nyní nasměrujte prohlížeč na http://127.0.0.1:3000/books a začněte hledat. Jakmile zadáte do políčka první znaky, zobrazí se výsledky. Klepněte na jeden z nabízených odkazů a sledujte, co se stane. Zdrojový kód je zde.