我在顯示用戶使用索引操作時的問題列表。我想過濾這個列表,只顯示被拒絕的問題,只有圖像附加到他們的問題等。在Rails中篩選結果
你是如何做到這一點的?您是否只在索引操作中添加了代碼,用於檢查請求參數哈希中是否包含不同的已命名參數,並使用它們構建查詢。
myurl.com/questions?status=approved&only_images=yes
或者有更好的方法嗎?
我在顯示用戶使用索引操作時的問題列表。我想過濾這個列表,只顯示被拒絕的問題,只有圖像附加到他們的問題等。在Rails中篩選結果
你是如何做到這一點的?您是否只在索引操作中添加了代碼,用於檢查請求參數哈希中是否包含不同的已命名參數,並使用它們構建查詢。
myurl.com/questions?status=approved&only_images=yes
或者有更好的方法嗎?
爲了使您的控制器薄,避免意大利麪條代碼,你可以嘗試使用以下方法:
控制器:
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
您可以使用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
所以,我認爲有些地方你需要編碼才能在這樣的場景中表現出色;模型和控制器。
對於模型,您應該使用範圍。
#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過濾來自控制器中私有方法中視圖的所有不需要的過濾參數。
你能否解釋一下scope.scoped的功能和作用? – LuckyLuke 2012-08-10 10:24:53
'scope'只是一個變量名,它使ActiveRecord對象保持添加條件。 scope.scoped構造匿名作用域。 – dimuch 2012-08-10 13:22:39
啊,對。我明白。 – LuckyLuke 2012-08-10 13:42:55