ActiveRecord Rails 4,如何查看数组属性是否包含数组中的任何值



假设我有一个 Book 模型,它有一个类别属性,它是一个数组。 我想创建一个范围,我可以从要传入的另一个数组中获取至少包含一个项目的所有书籍。

在谷歌上广泛搜索并尝试了许多不同的查询之后,我发现的最接近的是:

Book.where("'Mystery' = ANY(categories)")

如何将"神秘"替换为类似于['Categ1', 'Categ2', etc...]的内容,以便我可以检索任何包含数组中至少一个值的书籍?

你需要知道三件事:

  1. PostgreSQL的数组重叠运算符:&&。 如果两个数组有任何共同的元素,则array1 && array2为 true。
  2. PostgreSQL的数组构造函数语法,即array[v1, v2, v3].
  3. 如果占位符的值是 Ruby 数组,则 ActiveRecord 会将?占位符替换为逗号分隔的列表,以便where('c = any(array[?])', [1,2,3])到达数据库时看起来像c = any(array[1,2,3])

如果你把所有这些放在一起,你会得到这样的东西:

categories = %w[Categ1 Categ2 Categ3]
Book.where('categories && array[?]', categories)

您的范围将是这样的:

scope :with_any_categories, ->(cats) { where('categories && array[?]', cats) }

或者也许:

scope :with_any_categories, ->(*cats) { where('categories && array[?]', cats.flatten) }

具体取决于您希望如何使用范围。