Rails在范围内选择,虚拟属性返回一个空的ActiveRecord关系

时间:2014-07-12 11:55:34

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

在使用MySQL的Rails 4.1.2应用程序中,我正在执行以下操作:

scope :popular, -> {
  select("images.*, SUM(likes_count + comments_count + reposts_count) as score").
  where("DATE(created_at) > DATE(?)", 4.weeks.ago).
  order('score DESC')
}

获取最近的一组“热门”图片。问题是,如果没有与此查询匹配的图像,我会得到一个包含所有nil值的ActiveRecord::Relation,例如......

#<ActiveRecord::Relation [#<Image id: nil, user_id: nil, image_uid: nil, image_name: nil>]>

由于集合不为空,这会导致问题。如果没有结果,我如何让该范围返回'nil',或者如果对象是空的或什么东西则拒绝该范围?

更新

Image.popular.select {|i| i.id.present? }

有点解决问题,但对我来说,这似乎更像是一种解决方法而非解决方案......

1 个答案:

答案 0 :(得分:1)

您可以确保没有返回nil id值的任何内容。也许是这样的事情:

scope :popular, -> {
  select("images.*, SUM(likes_count + comments_count + reposts_count) as score").
  where("DATE(created_at) > DATE(?) AND id IS NOT NULL", 4.weeks.ago).
  order('score DESC')
}

修改

另一种方法是通过在模型上缓存score属性来简化查询。生成迁移并将属性添加到模型中。然后,使用before_save回调:

before_save :cache_score

def cache_score
  self.score = likes_count + comments_count + reposts_count
end

然后你可以简化你的查询:

scope :popular, -> { where("created_at > ?", 4.weeks.ago).order('score DESC') }