使用类似查询干燥多个范围

时间:2015-04-12 21:10:33

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

我注意到我的示波器的趋势,并试图弄清楚如何使其干燥

scope :newest, -> { order('created_at DESC') }
scope :top_sold, -> { order('qty_sold DESC') }
scope :most_viewed, -> { order('qty_viewed DESC') }
scope :most_downloaded, -> { order('qty_download DESC') }
scope :most_favorited, -> { order('qty_favorited DESC') }

我想传递我想要排序的列,以便我可以在Photo上调用它。我试过这个,但遇到了问题

scope :sort_photos, -> type { order('type DESC') }
Photo.sort_photos('qty_download')

我是在正确的道路上还是有更聪明的方法来实现这一目标?

2 个答案:

答案 0 :(得分:1)

type作为范围参数传递,并在order子句中使用字符串插值:

scope :sort_photos,->(type) { order("#{type} DESC") }

然后做:

Photo.sort_photos('qty_download')

答案 1 :(得分:1)

order方法采用String或Hash。因此,您可以order('created_at DESC')代替order(created_at: :desc),而不是type。所以,要完成你想要的东西,就像将密钥更改为scope :sort_photos, -> type { order(type => :desc) } 变量一样简单:

order

我还建议您为by_范围使用哨兵,例如by_sort_photos。因此,范围sort_photos不会被scope :newest, -> { by_most_recent_type('created_at') } scope :top_sold, -> { by_most_recent_type('qty_sold') } scope :by_most_recent_type, -> type { order(type => :desc) } 方法的定义或稍后的结果覆盖。

最后,拥有一个充满方法的公共接口,而不是需要知道类属性并将这些属性名称传递给公共接口方法,这样做是件好事。所以我保留了你拥有的许多不同的范围,但也许它们都引用了我们在这里定义的一般范围。所以:

{{1}}