2012-08-10 83 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 2012-08-10 10:24:53

+0

'scope'只是一個變量名,它使ActiveRecord對象保持添加條件。 scope.scoped構造匿名作用域。 – dimuch 2012-08-10 13:22:39

+0

啊,對。我明白。 – LuckyLuke 2012-08-10 13:42:55

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過濾來自控制器中私有方法中視圖的所有不需要的過濾參數。