2012-08-05 39 views
1

我有一個模型的索引視圖,我想通過模型的某些屬性組合來過濾。Rails 3:使用範圍在索引視圖上構建一組過濾器

例如,我有一個Bill模型(不是那種你必須付錢的鴨子),我可能會過濾收款人和/或狀態。

該模型具有用於每個單獨屬性的範圍,例如,

scope :bill_status, lambda {|status| where("status = ?", status} 
scope :bill_payee, lambda {|payee| where("payee_id = ?", payee.id} 

該視圖允許用戶選擇零個或多個選項 - 如果沒有選擇一個選項,它的意思是「不通過此過濾器」。

在控制器中,我可以做一些令人討厭的是這樣的:

def index 
    status = params[:bill][:status] 
    payee = params[:bill][:payee] 
    if status.present? and payee.present? 
    # chain scopes 
    @bills = Bill.bill_status(status).bill_payee(payee) 
    elsif status.present? 
    @bills = Bill.bill_status(status) 
    elsif payee.present? 
    @bills = Bill.bill_payee(payee) 
    else 
    @bills = Bill.all 
    end 

    # rest of controller action 
end 

不過,雖然這工作,它既不漂亮也不容易擴展 - 增加了第三濾波器裝置我現在有很多可能性。我尋求美麗和純潔。

在假設我的範圍是所有可鏈接的,好像我應該能夠做到像

def index 
    @bills = Bill.all 
    @bills = @bills.bill_status(params[:bill][:status]) if params[:bill][:status].present? 
    @bills = @bills.bill_payee(params[:bill][:payee]) if params[:bill][:payee].present? 

    # rest of controller code 
end 

東西「CEPT這是行不通的,因爲Bill.all是一個數組。另外,這並不好玩,因爲Bill.all執行查詢,我只想運行一次感謝AREL魔法。我應該只是定義一個範圍all_bills(沒有條件?) - 這將是一個ActiveRecord::Relation我猜...

有沒有一種模式,更優雅地解決這個問題?每當我有代碼去做一件依賴於模型,視圖和控制器的事情時,我覺得我可能會做錯某些事情。或者就像有人比我已經解決它更聰明,更難工作:-)

獎金的問題:我希望這一切與我的選擇,最優秀的Kaminari寶石的paginator工作。

歡迎所有的想法和想法。

+1

你試過has_scope嗎?我剛剛在另一個問題上推薦了這個問題http://stackoverflow.com/a/11820424/167614 – 2012-08-05 22:27:08

+0

嗨@beerlington has_scope寶石看起來很有趣,它的Platformatec工作人員的血統是無可挑剔的。我偏袒@ mu-is-too-short的另一個線索的答案,它解決了我的方法的一個基本問題 - 而不是以@bills = Bill.all開頭我可以用@bills =比爾「(它提供了AREL範圍鏈接的基礎),然後用'@bills = @ bills.all'在最後運行整個事情。兩種解決方案都很棒。現在確保他們都與Kaminari合作進行分頁。謝謝。 – 2012-08-06 00:21:26

+1

has_scope肯定會與will_paginate一起使用,所以如果它不適用於Kaminari,我也會感到驚訝。 – 2012-08-06 00:45:27

回答

1

當我搜索的解決方案,似乎像一個共同的問題,我檢查了Ryan Bates'RailsCast and found an episode from 3 days ago on Ransack。 Ransack對於表單搜索和列排序來說是一個非常酷的寶石,我認爲這就是我要去的方式。

感謝這裏的答案 - 我很高興從花費時間和努力的人那裏學到了一些很棒的技術。

+0

自問我以來的更新 - 我已經使用Ransack 0.7,它是一個軟件的輝煌,對文檔有點光,但整體非常優雅 - 視圖不需要特殊的標記按照慣例爲搜索字段(非常Railsy ),控制器中有一條額外的線,模型中沒有任何內容。 – 2012-08-14 13:05:47

4

我會做這樣的事情:

proxy = Bill.scoped 
if status.present? 
    proxy = proxy.bill_status(status) 
end 
if payee.present? 
    proxy = proxy.bill_payee(payee) 
end 

@bills = proxy 

你甚至可以做那麼一些元編程:

@bills = [:status, :payee, ...].inject(Bill.scoped) do |proxy, param| 
    val = params[:bill][param] 
    val.present ? proxy.send("bill_#{param}", val) : proxy 
end 
+0

非常好:-)。就像元編程解決方案 - 有點侷限於本地和魔術! – 2012-08-06 12:56:44

相關問題