2012-08-05 41 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

相关问题