Wyszukiwanie

Witam.

Mam na podstawie railscastsa ‘simple search’ zrobione wyszukiwanie.
W railscascie jest jedno pole text_form i adres wygląda tak:
adres.pl/products?search=costam.
Potem widokwygląda tak:

def self.search(search) if search find(:all, :conditions => ['name LIKE ?', "%#{search}%"]) else find(:all) end end
i OK.

Ja natomiast dodałem jeszcze kilka innych pół select.
I adres wyglada tak:
adres.pl/products?search=costam&category=2&place=3&comment=5

Jak teraz zgrabnie to wykonać, aby nie robic:

if search find(:all, :conditions => ['name LIKE ?', "%#{search}%"]) if category .... if place ..... if comment .... ..... end end end
I tak takim kodem nie zabezpiecze sie przed sytuacja gdy np category=nil.
Kombinacje wyszukiwania czy filtrowania (i ta i ta nazwa chyba dobra) moga być dowolne.
Jak to ładnie zapisać?

Myślałem o named_scopach i potem jakoś to zgrabnie łączyć. Tylko jak?
Liczę na jakieś sugestie.

A moze tez jakiś sposób na pozbycie sie tego mało eleganckiego adresu adres.pl/products?search=costam&category=2&place=3&comment=5.

Widziałem railscastsa 111 Advanced Search Form, ale jakoś nie podoba mi się ze zapisywane jest do bazy każde wyszukiwanie.

Pozdrawiam

Jest taki fajny plugin Ryana Batesa scope_builder.

Używa się mniej więcej tak (w połączeniu z pluginem quick scopes, który udostępnia kilka dodatkowych: limit, where, with i order):

@articles = Article.scope_builder @articles.where(:category_id => params[:category_id]) if params[:category_id] @articles.where(['name LIKE ?', "%#{params[:query]}%"]) if params[:query] @articles = @articles.paginate(:per_page => 20, :page => params[:page]
Jak potrzebujesz czegoś bardziej zaawansowanego, to zainteresuj się search logic.

UPDATE:
I oczywiście najlepiej to przerzucić do modelu, a kryteria mieć w jednym miejscu, na przykład:
{:search => {:query => “costam”, :category_id => 1, :foobar => 3}} tak, żeby można to było łatwo przekazać:

Article.search(params[:search]

Lopez
moja wersja jest nastepujaca:

controller:

[code]# przechwytujesz parametry z formularza (post)

i wywolujesz metode search w modelu

@results = ModelName.search(params[:form_name])[/code]
model:

[code]# np. form_name => { :name => ‘slawek’, :age => ‘30’, :occupation => ‘’ }
def self.search(params)
raise ‘searching form is empty’ if params.values.to_s.empty?

preparing query

arr = []
params.each_pair do |key, value|
arr << “#{key} LIKE ‘%#{value}%’” unless value.empty?
end

conditions = “age LIKE ‘%30%’ AND name LIKE ‘%slawek%’”

find(:all, :conditions => arr.join(’ AND '))

rescue Exception => e
logger.info(e)
find(:all)
end[/code]

  • dzieki takiem rozwiazaniu nie musisz zmieniac metody search za kazdym razem jak zmieni sie formularz
  • funkcja each_pair i join tworza kwerende na podstawie przekazanego słownika
  • jezeli wartosci w przekazanym slowniku sa puste - metoda search szuka wszystkich rekordow
  • oczywiscie trzeba zadbac, aby tych wynikow nie bylo za duzo
  • najlepiej zastosowac funkcje paginate (do methody search trzeba wtedy przekazac parametr :page)
  • a jeszcze lepiej zastosowac SPHINX’a (jezeli duzo rekordow to przeszukania - z duza iloscia parametrow do wyszukania)

pozdrawiam

[quote=drogus]I oczywiście najlepiej to przerzucić do modelu, a kryteria mieć w jednym miejscu, na przykład:
{:search => {:query => “costam”, :category_id => 1, :foobar => 3}} tak, żeby można to było łatwo przekazać:

Article.search(params[:search]

[/quote]
Jak powinien wyglądać formularz aby taki efekt osiągnąć?
Zrobiłem tak:

[code=“ruby”]<% form_for articles_path, :action => ‘search’, :method => ‘post’ do |f| %>

<%= f.text_field :title %> <%= f.submit 'Szukaj' %>

<% end %>[/code] Ale coś nie dizała bo wrzuca mnie na stronę z dodawaniem nowego artykułu.

A jak chciałbym, aby adres wyglądał tak: localhost:3000/articles/search
i potem postem wysłać parametry?

Tylko że tu potrzeba jeszcze :id artykułu aj ja go nie będę przecież miał.

Póki co mam działające wyszukiwanie ale z adresem :slight_smile:
localhost:3000/articles?category=3&maker=1&tags=polska
i w kontrolerze :slight_smile:
kupa ifów sprawdzających czy dane pole wybrane.
Wiem okropnie to wygląda i chcę to poprawić.
a chciałbym
http://localhost:3000/developments/search

Oto mój okropmny kontroler:

def index if params[:category].blank? and params[:maker].blank? and params[:tags].blank? @articles= Article.all.paginate(:page => params[:page], :per_page => 5) else if params[:tags].blank? @articles= Article.category(params[:category]).maker(params[:maker]).paginate(:page => params[:page], :per_page => 5) else @articles= Article.category(params[:category]).maker(params[:maker]).find_tagged_with(params[:tags].downcase, :match_all => true).paginate(:page => params[:page], :per_page => 5) end end end
Bleee

Binarylogic’s Searchlogic – spróbuj tego, a zapomnisz o innych pluginach do filtrowania / budowania find’ów :slight_smile:

Z tego co widzę to adres nie wygląda za ciekawie.

U mnie tak teraz:

http://localhost:3000/articles?search[order_by]=BAhbByIPaXNzdWVfeWVhciIKdGl0bGU%3D &search[order_as]=ASC&search[per_page]=25&search[priority_order_by]=&search[priority_order_as]=&search[conditions][title]=%PVT%&commit=Search

Hmmm, tak ma być?

Pozdrawiam

hmn, też mam mały kłopot z tym simple search’em, chodzi mi o to, że mam listę postów, gdzie m.in. wyświetlane są kategorie. Chciałbym aby po kliknięciu w kategorie wyświetlały się wszystkie posty o danej kategorii, ale nie wiem jak przekazać parametr do metody search przez kliknięcie w link - chodzi mi o coś takiego:

uwaga - trochę pseudokod:

<%= link_to post.category, posts_path, params[:search] = post.category %>

gdzie:

<% link_to nazwalinku, lista_postów (wyświeltana poprzez właśnie tą metodę search, w przypadku gdy nie ma podanych żadnych argumentów wyświetla mi wszystkie posty ładnie), parametr_potrzebny_metodzie_search %>

Jak sprawić, aby ten parametr został przekazany metodzie search?

A, i mój search w modelu wygląda tak:

def self.search(search) if search find(:all, :conditions => ['category LIKE ?', "#{search}%"]) else find(:all) end end
EDIT:

Problem rozwiązany :slight_smile:

 <%= link_to post.category, :search => post.category %>