2009-06-01 6 views
21

나는 장고에 대해 여러 가지 필터 방법을 실행할 수 있습니다. 예를 들어 Item.all.filter(foo="bar").filter(something="else")입니다.레일에서 ActiveRecord 쿼리 필터링

그러나 이것은 레일스에서 ​​그리 쉬운 일이 아닙니다. Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }]) 수익률이 작동하지 않습니다 의미 배열 :

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

그래서 난에 "스택"필터 조건 배열을 수정 한 다음 쿼리를 실행하는 가장 좋은 방법을 생각.

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 

사용법 :

하는 array1 = [ "foo는 = foo는"{: foo는 = '바'}] 배열 2 = [ "뭔가

그래서 나는이 기능을 함께했다 = : something ", {: something = 'else'}] 조건 = 결합 (array1, array2) items = item.find (: all, : conditions => 조건)

이것은 꽤 잘 작동했습니다. 그러나 임의의 수의 배열을 결합하거나 기본적으로 쓰기를 위해 단축 할 수 있기를 원합니다.

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

아무도 도와 줄 수 있습니까? 미리 감사드립니다.

답변

35

당신이 지정됩니다 원하는 범위 : 당신의 컨트롤러에서

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 

, 다음과 같이 사용

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 

반환 된 객체가 프록시와 SQL 쿼리가 실제로 때까지 실행되지 않습니다됩니다 iterating (표시 용) 또는 프록시에서 Enumerable 메서드를 호출 할 때와 같이 콜렉션에서 실제 작업을 시작하십시오.

+0

그래, 내가 원하는 바로 그 것이다. 나는 스크린 캐스트를 보았고 그것은 나에게 완전한 의미를 가졌다. 그러나 코드를 실행하자마자 명명 된 범위가 정의되지 않은 메서드라는 오류가 발생했습니다. 그런 다음 레일스 1.8으로 작업 중이라는 것을 알게되었으므로 레일을 2.3.something으로 업데이트하고 여전히 동일한 오류가 발생했습니다 .... 우물로 명명 된 스코프가 너무 좋았습니다 :/ – user94154

+1

레일을 동결했다면, 코드는 여전히 이전 버전의 레일즈를 사용하고 있습니다. Rails 1.8은 존재하지 않았으므로 Ruby 1.8을 의미해야합니다. rails -v는 명령 줄에서 Rails의 버전을 알려주는 명령입니다. script/about은 응용 프로그램 환경에 대해 자세히 알려줍니다. –

+0

루비 스크립트/약을 인식하지 못했습니다. Rails의 관점에서 고정 된 것은 무엇입니까? – user94154

1

Searchlogic을 살펴볼 수 있습니다.
ActiveRecord 세트의 조건을 더 쉽게 사용하고 심지어 Arrays에도 조건을 사용합니다.

희망이 있습니다.

4

나는 당신이 원하는 것은이 생각 :

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

여기서 : foo에와 : 바 필드 당신은 레일과 같이 필터링 (또는 적어도 할 수 있도록 사용) 할 수 Named Scope

1

활성 레코드의 이름. 필드 이름 => 값 쌍의 해시를 전달하면됩니다.

+0

이것은 나를 위해 일했습니다 (나는 1.8에 있습니다.7) – John

6

나는 당신이 제안한 것처럼하지 않을 것입니다. 배열을 반환 찾을 수 있기 때문에

, 당신은 예에, 그것을 필터링 배열 방법을 사용할 수 있습니다

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

당신은 또한 당신의 이름 범위와 원하는 achive 수 있습니다.

+1

명명 된 범위는이 작업을 수행하는 훨씬 더 좋은 방법이며 사용할 수있는 쉽게 사용할 수있는 체인 가능한 메서드를 제공합니다. – nitecoder

+1

@railsninja : 동의 하긴하지만 사용하기 전에 명명 된 범위를 정의해야합니다. 한 번만 작업하려면 select를 사용하는 것이 더 쉽습니다. – klew

+2

사실이 아닙니다. 즉석에서 익명 범위를 수행 할 수 있습니다. http://railscasts.com/episodes/112-anonymous-scopes –

관련 문제