2012-08-10 4 views
0

사용자가 색인 작업을 사용할 때 질문 목록을 표시하고 있습니다. 이 목록을 필터링하여 거부 된 질문 만 표시하고 이미지에만 첨부 된 질문 만 표시합니다.Rails에서 결과 필터링

어떻게 작성합니까? 서로 다른 명명 된 매개 변수가 요청 매개 변수 해시에 있는지 확인하고 쿼리를 작성하는 코드를 색인 작업에 추가하기 만하면됩니다.

myurl.com/questions?status=approved&only_images=yes 

더 좋은 방법이 있습니까?

답변

1

는 방법으로 다음을 사용하려고 할 수 얇은 컨트롤러를 유지하고 스파게티 코드를 방지하려면 :

컨트롤러 :

def index 
    @questions = Question.filter(params.slice(:status, :only_images, ...) # you still can chain with .order, .paginate, etc 
end 

모델 :

def self.filter(options) 
    options.delete_if { |k, v| v.blank? } 
    return self.scoped if options.nil? 
    options.inject(self) do |scope, (key, value)| 
     return scope if value.blank? 
     case key 
     when "status" # direct map 
      scope.scoped(:conditions => {key => value}) 
     when "only_images" 
      scope.scoped(:conditions => {key => value=="yes" ? true : false}) 
     #just some examples 
     when "some_field_max" 
      scope.scoped(:conditions => ["some_field <= ?", value]) 
     when "some_field_min" 
      scope.scoped(:conditions => ["some_field >= ?", value]) 
     else # unknown key (do nothing. You might also raise an error) 
      scope 
     end 
    end 
    end 
+0

scope.scoped가 무엇을하고 작동하는지 조금 설명해 주시겠습니까? – LuckyLuke

+0

'scope'는 단지 변수 이름이며, 조건이 추가 된 ActiveRecord 객체를 유지합니다. scope.scoped는 익명 범위를 생성합니다. – dimuch

+0

아 맞아. 이해 했어. – LuckyLuke

3

당신은이 작업을 수행 할 has_scope을 사용할 수 있습니다 우아하게 :

# Model 
scope :status, proc {|status| where :status => status} 
scope :only_images, ... # query to only include questions with images 

# Controller 
has_scope :status 
has_scope :only_images, :type => boolean 

def index 
    @questions = apply_scopes(Question).all 
end 
0

그런 시나리오에서 좋은 코드를 작성해야하는 곳이 있다고 생각합니다. 모델과 컨트롤러.

모델의 경우 범위를 사용해야합니다. 컨트롤러의

#Model 
scope :rejected, lambda { where("accepted = false") } 
scope :accepted lambda { where("accepted = true") } 
scope :with_image # your query here 

,

def index 
    @questions = @questions.send(params[:search]) 
end 

당신은 UI에서 메소드 이름을 보내 직접 모델의 범위에 그것을 전달할 수있다. 또한 UI에서 다시 전달하여 .all 케이스의 "if"조건을 피할 수 있습니다.

그러나 모델 코드를 직접 볼 수 있으므로 before_filter를 사용하여 컨트롤러의 개인 메서드에서보기에서 오는 원치 않는 필터 매개 변수를 필터링해야합니다.