我的House
模型具有price
属性,该属性是使用实例方法计算的。
让我们说价格因市场利率,通货膨胀等而不断变化。因此,我们需要一种price_today
方法来获得当前价格。
如何使用最高价格和最低价格创建命名范围(或其他内容)来过滤房屋?
我尝试过做这样的事情,但我觉得这有点像个hacky ......
def index
@houses = # get houses from DB
if not params[:max_price].nil?
@houses.keep_if { |h| h.price_today <= params[:max_price].to_f }
end
if not params[:min_price].nil?
@houses.keep_if { |h| h.price_today >= params[:min_price].to_f }
end
end
答案 0 :(得分:1)
命名范围(或where
子句)查询和过滤实例化对象肯定会更快。
但是,我担心如果数据库中不存在price_today
,您将无法使用它们。
但是,您可以改进代码
条件可以更简单,您只需拨打一次keep_if
。
max = params[:max_price].presence
min = params[:min_price].presence
if max || min
@houses.keep_if do |house|
a = max ? (house.price_today <= max.to_f) : true
b = min ? (house.price_today >= min.to_f) : true
a && b
end
end
如果您愿意,可以使用select
而不是keep_if
。
答案 1 :(得分:0)
另一种变化:
{ max_price: ->(price, max) { price <= max },
min_price: ->(price, min) { price >= min } }.each { |prop, cond|
@houses.select! { |h| cond.(h.price_today, params[prop].to_f) } unless params[prop].nil?
}
对于特殊属性的lambda,您可以轻松添加另一个条件=)