2009-06-01 19 views
21

Ben querysets, yani Item.all.filter(foo="bar").filter(something="else"), yani birden çok filtre yöntemleri çalıştırabilirsiniz Django için kullanılır. Bununla birlikte, Rails'de yapılması bu kadar kolay değildir. Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }]) döner bu çalışmaz yani bir dizi: Raylarda ActiveRecord sorgularını filtreleme

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

yüzden etmek "yığın" filtreleri koşullar dizisini değiştirebilir ve daha sonra sorguyu çalıştırmak için en iyi yol buldum.

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 

Kullanımı:

dizi1 = [ "foo =: ​​foo", {: foo = 'bar'}] dizi2 = [ "şey

Bu yüzden bu fonksiyonu ile geldi =: bir şey", {: bir şey = 'else'}] koşullar = birleştirmek (dizi1 dizi2) ürün = Item.find (: tümü,: koşullar => koşullar)

Bu oldukça iyi çalıştı. Ancak yazma diziler isteğe bağlı sayıda birleştirmek veya temelde steno edebilmek istiyorum:

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

kimse bu konuda yardımcı olabilir misiniz? Şimdiden teşekkürler.

cevap

35

sen adlandırılır istediğiniz ne kapsamları: En kontrolörleri ise

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 

böyle kullanın:

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 

döndürülen nesne bir proxy ve SQL sorgusu aslında sizin kadar çalışacak olmayacak edilir Yinelenen (görüntüleme için) veya proxy'de Enumerable yöntemlerini çağırdığınızda, koleksiyonla gerçek bir şeyler yapmaya başlayın.

+0

Evet, tam olarak istediğim bu. Screencast'ı izledim ve bana tamamen mantıklı geldi. Ama kodu ilk başlattığımda, adlandırılmış kapsamın tanımlanmamış bir yöntem olduğunu söyleyen bir hata aldım. Sonra ben Rails 1.8 ile çalıştığımı fark ettim, bu yüzden 2.3.something rails güncellendi ve hala aynı hatayı aldım .... ugh, isimleri kapsamları gerçek olamayacak kadar iyi olduğunu biliyordum:/ – user94154

+1

Eğer Rails donduysa, o zaman kodunuz hala bir önceki Rails sürümünü kullanıyor. 1,8 Raylar asla var olmadı, bu yüzden Ruby 1.8 demek gerekir. raylar -v, komut satırında Rails'in hangi sürümünün bulunduğunu size söyleyen bir komuttur. script/about, uygulamanızın ortamı hakkında daha fazla bilgi verecektir. –

+0

kuyu ruby ​​script/hakkında tanınmadı. Dondurulmuş Raylar açısından ne anlama geliyor? – user94154

1

Searchlogic'a bakabilirsiniz.
ActiveRecord kümelerinde ve hatta Arrays numaralı ortamlarda kullanım koşullarını daha kolay hale getirir.

Yardım edin.

4

Ben ne istediğini bu olduğunu düşünüyorum:

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

burada:: foo ve: Çubuk alandır Sen Rails şöyle filtre (veya en azından edebilmek için kullanılan) olabilir Named Scope

1

aktif kayıttaki isimler. Yapmanız gereken tek şey şunun içinde bir karmaşayı geçmek gibi görünüyor: field_name => değer çiftleri.

+0

Bu benim için çalıştı (1.8 yaşıyorum.7) – John

6

Bunu önerdiğiniz gibi yapmam. Bir dizi döndürür bulmak yana

, örneğin üzerine, filtrelemek dizi yöntemleri kullanabilirsiniz:

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

Ayrıca adlandırılmış kapsamları ile istediğinizi elde edebilirsiniz.

+1

Adlandırılmış kapsamlar bunu yapmanın daha iyi bir yoludur ve kullanabileceğiniz kolayca kullanılabilir zincirlenebilir yöntemler sağlar. – nitecoder

+1

@railsninja: Katılıyorum, ancak kullanmadan önce adlandırılmış alanı tanımlamanız gerekiyor. Eğer sadece bir kez bir şeyler yapmak istiyorsanız, seçim yapmak daha kolaydır. – klew

+2

Doğru değil. Anonim kapsamları anında yapabilirsiniz: http://railscasts.com/episodes/112-anonymous-scopes –