Příspěvky se štítkem ‘živé vyhledávání’

Živé vyhledávání v textu u Ruby on Rails

18. 7. 2008 v 23.46

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

  1. Vytvoříme prázdnou aplikaci - jednoduchou databázi knížek
  2. Přidáme možnost vyhledávat v textech
  3. Zprovozníme živé vyhledávání
    1. Vytvoříme dílčí formulář (partial) pro vyhledávání - tam se bude zadávat dotaz
    2. Vytvoříme dílčí panel (partial) pro výsledky - tam budou nabízeny mezivýsledky hledání
    3. 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

rake db:migrate

Nastartujeme vývojový server

ruby script/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.