Rails/SQL 结合 rails 范围的条件

Rails/SQL combine where conditions for rails scope

我想获得除 [30, 54] 和 language_id 之外 language_id 的项目总数:无

LOCALES = {
  non_arabic_languages: {
    id: [30, 54]
  }
}

  scope :non_arabic_languages, -> { where.not(language_id: LOCALES[:non_arabic_languages][:id]) || where(language_id: nil) }

这个例子可以预见returns第一部分,所以我只得到非阿拉伯语的项目。 && 也有问题。我该如何组合它?我们将感谢您的建议!

您陷入了一个常见的陷阱,您将 Ruby 中的逻辑操作与通过 ActiveRecord 查询接口实际创建 SQL 混淆了。

使用 || 将 return 第一个真实值:

where.not(language_id: LOCALES[:non_arabic_languages][:id]) || where(language_id: nil) 

这是 return 由 where.not(language_id: LOCALES[:non_arabic_languages][:id]) 编辑的 ActiveRecord 关系,因为在 Ruby 中除了 false 和 nil 之外的所有内容都是真实的。 || where(language_id: nil) 从未实际计算过。

在 Rails 中添加了对 .or 的支持 5. 在以前的版本中,最直接的解决方案是使用 Arel 或 SQL 字符串:

scope :non_arabic_languages, -> { 
  non_arabic_languages_ids = LOCALES[:non_arabic_languages].map { |h| h[:id] }
  where(arel_table[:language_id].not_in(non_arabic_languages_ids ).or(arel_table[:language_id].eq(nil)))
}

我会留下标记评论(如@fixme),以便您在升级到 5.0 后修复此问题,或者考虑一个更好的解决方案,首先不涉及硬编码数据库 ID,例如使用 natural key.