【问题标题】:Rails select in scope with virtual attribute returns an empty ActiveRecord Relation具有虚拟属性的范围内的 Rails 选择返回一个空的 ActiveRecord 关系
【发布时间】:2014-07-12 11:55:33
【问题描述】:

在带有 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? }

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

【问题讨论】:

  • scope 将始终返回AR,您可以使用#blank?#present? 进行测试...
  • 空白?返回假,存在吗?返回 true - 正如我所说的集合不是空的,所以这不起作用:(

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


【解决方案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') }

【讨论】:

    猜你喜欢
    • 2014-06-18
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 1970-01-01
    相关资源
    最近更新 更多