Wyszukiwanie

SQL v. zewnętrzna wyszukiwarka + gem.

Searchlogic

Zaczynamy od screencastu Simple Search Form pokazującego jak zaimplementować proste wyszukiwanie.

My zaimplementujemy w Fortunce coś bardziej skomplikowanego — tak jak w przykładzie ze screencastu Searchlogic.

Instalacja gemu

Dopisujemy do config/environment.rb:

config.gem "searchlogic"

i sprawdzamy na konsoli jak działa Searchlogic:

Fortune.author_like('Einstein')
Fortune.author_not_like('Einstein')
Fortune.author_like('Einstein').quotation_like('God') # AND
Fortune.quotation_like_any(['God', 'never']) # OR
Fortune.quotation_like_all(['God', 'Before']) # AND
User.roles_name_like('admin')
User.roles_name_like('owner')

Można wyszukiwać też tak:

Fortune.search(:author_like => 'Einstein') # Search object
Fortune.search(:author_like => 'Einstein').all
Fortune.search(:author_like => 'Einstein', :quotation_like => 'God').all
s = Fortune.search(:author_like => 'Einstein')
s.quotation_like('God').all # composition

Inne rzeczy, nie będące wyszukiwaniem:

Fortune.published_equals(true)
Fortune.ascend_by_author

Proste wyszukiwanie po autorach

Zauważmy, że to_s poniżej „daje opcjonalny author_like_any”:

@fortunes = Fortune.author_like_any(params[:search].to_s.split)

Jest tak ponieważ

nil.to_s # => ""
nil.to_s.split # => []

Zatem, jeśli nic nie wpisano, czyli params[:search] = nil, to zdefiniowana powyżej tablica @fortunes równa się tablicy

Fortune.all

Kontroler:

class FortunesController < ApplicationController
  def index
    @main = Fortune.published_equals(true).
      author_like_any(params[:search].to_s.split).
      paginate(:page => params[:page],
               :order => 'created_at DESC')
  end
end

Formularz:

<h3>Search by author</h3>
<%- form_tag root_path, :method => 'get' do -%>
  <p>
    <%= text_field_tag 'search', params[:search] %>
    <%= submit_tag "Submit", :name => nil %>
    </p>
<%- end -%>

Wyszukiwanie po fortunkach

Zaawansowane wyszukiwanie, tj. wyszukiwanie po autorach i po cytatach.

Zaczniemy od przerobienia w layoucie main.html.erb formularza:

<h3>Search by author</h3>
<%- form_tag search_path, :method => 'get' do -%>
  <p>
    Author:<br/>
    <%= text_field_tag 'a', params[:a] %>
  </p>
  <p>
    Quotation:<br/>
    <%= text_field_tag 'q', params[:q] %>
  </p>
  <p>
    <%= submit_tag "Submit", :name => nil %>
  </p>
<%- end -%>

i dodajemy nową named route:

map.search "search", :controller => "main", :action => "search"

Następnie, w kontrolerze MainController wydzielamy z metody index metodę search, tak aby URL-e były bardziej przyjazne:

class MainController < ApplicationController
  def index
    @subtitle = "Recent"
    @main = Fortune.published_equals(true).
      paginate(:page => params[:page],
               :per_page => 4,
               :order => 'created_at DESC')
  end

  def search
    @subtitle = "Results"
    @main = Fortune.published_equals(true).
      author_like_any(params[:a].to_s.split).
      quotation_like_any(params[:q].to_s.split).
      paginate(:page => params[:page],
               :per_page => 4,
               :order => 'created_at DESC')
    render :action => 'index'
  end
end

Sphinx

TODO gem Thinking Sphinx.

Xapian

TODO gem Xapit.

Links