2009-06-01 10 views
21

Jestem przyzwyczajony do Django, gdzie można uruchomić wiele metod filtrowania w zestawach zapytań, tj. Item.all.filter(foo="bar").filter(something="else").Filtrowanie zapytań ActiveRecord w szynach

To jednak nie jest takie łatwe w Railsach. Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }]) Zwraca tablicę czyli to nie będzie działać:

Item.find(:all, :conditions => ["foo = :foo", { :foo = 'bar' }]).find(:all, :conditions => ["something = :something", { :something = 'else' }])

więc pomyślałem, że najlepszym sposobem na filtry „komin” to zmodyfikować tablicę warunków, a następnie uruchomić kwerendę.

Więc wymyśliłem tej funkcji:

def combine(array1,array2) 
    conditions = [] 
    conditions[0] = (array1[0]+" AND "+array2[0]).to_s 
    conditions[1] = {} 
    conditions[1].merge!(array1[1]) 
    conditions[1].merge!(array2[1]) 
    return conditions 
end 

Zastosowanie:

array1 = [ "foo =: ​​foo", {: 'bar' foo =}] tablica2 = [ "coś =: coś”, {: coś = 'else'}] warunki = Połącz (array1, tablica2) szt = Item.find (: all,: conditions => warunki)

ten pracował całkiem dobrze. Jednak chcę być w stanie połączyć dowolną liczbę tablic lub po prostu skrótem zapisu:

conditions = combine(combine(array1,array2),array3) 

Czy ktoś może pomóc? Z góry dziękuję.

Odpowiedz

35

co chcesz są nazwane podzbiory:

class Item < ActiveRecord::Base 
    named_scope :by_author, lambda {|author| {:conditions => {:author_id => author.id}}} 
    named_scope :since, lambda {|timestamp| {:conditions => {:created_at => (timestamp .. Time.now.utc)}}} 
    named_scope :archived, :conditions => "archived_at IS NOT NULL" 
    named_scope :active, :conditions => {:archived_at => nil} 
end 

W kontrolerach, należy tak:

class ItemsController < ApplicationController 
    def index 
    @items = Item.by_author(current_user).since(2.weeks.ago) 
    @items = params[:archived] == "1" ? @items.archived : @items.active 
    end 
end 

Zwrócony obiekt jest pełnomocnikiem i zapytań SQL nie będą działać aż faktycznie zacznij robić coś rzeczywistego z kolekcją, taką jak iteracja (do wyświetlenia) lub po wywołaniu metod pełnych na serwerze proxy.

+0

Tak, dokładnie to, czego chcę. Oglądałem screencast i było to dla mnie całkowicie zrozumiałe. Ale gdy tylko uruchomiłem kod, otrzymałem komunikat, że nazwany zakres jest niezdefiniowaną metodą. Potem zauważyłem, że pracowałem z Rails 1.8, więc klejnot zaktualizowałem tory do 2.3.something i nadal mam ten sam błąd .... ugh, wiedziałem, że nazwane zakresy były zbyt dobre, aby mogły być prawdziwe:/ – user94154

+1

Jeśli zamroziłeś Railsy, wtedy twój kod nadal używa poprzedniej wersji Rails. Railsy 1.8 nigdy nie istniały, więc musisz mieć na myśli Ruby 1.8. rails -v to polecenie, które powie ci, jaka wersja Railsów istnieje w linii poleceń. skrypt/about powie Ci więcej o środowisku twojej aplikacji. –

+0

również skrypt ruby ​​/ o nie został rozpoznany. Co oznacza zamrożone pod względem Railsów? – user94154

1

Możesz spojrzeć na Searchlogic.
Ułatwia korzystanie z warunków na zestawach ActiveRecord, a nawet na Arrays.

Mam nadzieję, że to pomaga.

1

można (a przynajmniej kiedyś stanie) filtrować podobnie jak w Rails:

find(:all, :conditions => { :foo => 'foo', :bar => 'bar' }) 

gdzie: foo i bar to pole imiona w aktywnym rekordzie. Wygląda na to, że wszystko, co musisz zrobić, to przekazać skrót: field_name => wartości par.

+0

To zadziałało dla mnie (mam 1.8.7) – John

6

Nie zrobiłbym tego tak, jak zaproponowałeś.

Od znaleźć zwraca tablicę, można użyć metody tablicy do jej filtrowania, na przykład:

Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }... 

Można również achive co chcesz z wymienionych zakresów.

+1

Nazwane zakresy są o wiele lepszym sposobem na zrobienie tego i dają łatwe do użycia metody łańcuchowe, z których można korzystać. – nitecoder

+1

@railsninja: Zgadzam się, ale musisz zdefiniować nazwany zakres zanim go użyjesz. Jeśli chcesz zrobić coś tylko raz, łatwiej jest użyć wybierz. – klew

+2

Nieprawda. Możesz wykonywać anonimowe ustawienia w locie: http://railscasts.com/episodes/112-anonymous-scopes –

Powiązane problemy