Rails 4 - 以干燥的方式组合范围

时间:2016-11-22 09:58:08

标签: ruby-on-rails ruby-on-rails-4 activerecord

假设我有这3个范围:

scope :assembly_reclamation, -> { where(status: 5) }
scope :customer_reclamation, -> { where(status: 9) }
scope :wrong_delivery,       -> { where(status: 12) }

现在让我们说我想制作一个加入这3个类别的范围。我现在正在这样做:

scope :returnable, -> { where(status: [5, 9, 12]) }

虽然这有效,但它有一些缺点。如果我要改变3个类别中的一个的条件,我将不得不重新修改包含它们的范围。

这样的事情看起来更干嘛:

scope :returnable, -> { assembly_reclamation.or.customer_reclamation.or.wrong_delivery }

但这不是有效的代码。

有没有办法以这种方式编码?

更新

我知道我使用了类别和ID的示例,但请不要这样做。它是关于合并范围。

更新2 我已将属性的名称从id更改为status,因为每个人都专注于id的问题,而这不是问题的重点

1 个答案:

答案 0 :(得分:1)

如果你真的在处理category_ids,那么对于那些在Category模型中将这些ID作为常量读取代码的人来说更有意义:

class Category
  ASSEMBLY_RECLAMATION_ID = 5
  CUSTOMER_RECLAMATION_ID = 9
  WRONG_DELIVERY_ID       = 12
  RETURNABLE_IDS          = [ASSEMBLY_RECLAMATION_ID, CUSTOMER_RECLAMATION_ID, WRONG_DELIVERY_ID]
end

从现在开始,您可以在范围中使用这些常量,并且只更改常量,而不是范围的实现。

P.S。 Rails 5 added OR support,但在升级之前,它与您无关。

修改

组合少数范围的一种方法如下:

scope :returnable, lambda {
  where(id: assembly_reclamation.ids + customer_reclamation.ids + wrong_delivery.ids)
}