PostgreSQL позволяет применять логический оператор ко всему массиву значений, используя конструкцию op any(array_expr)
:
9.23.3.ЛЮБОЙ / НЕКОТОРЫЙ (массив)
expression operator ANY (array expression)
expression operator SOME (array expression)
Правая часть - это выражение в скобках, которое должно давать значение массива.Левое выражение оценивается и сравнивается с каждым элементом массива с использованием заданного operator
, что должно привести к логическому результату.Результат ANY
является «истинным», если получен какой-либо истинный результат.Результат равен «ложь», если истинный результат не найден (включая случай, когда массив имеет нулевые элементы).
PostgreSQL также поддерживает синтаксис конструктора массива для создания массивов:
array[value, value, ...]
Удобно, если ActiveRecord расширяет заполнитель как список с разделителями-запятыми, когда значение является массивом.
Объединение этих значений дает нам:
scope :by_templates, ->(templates) { joins(:template).where('templates.label ~* any(array[?])', templates) }
Кроме того, если вы используете оператор регулярного выражения без учета регистра (~*
) в качестве сравнения без учета регистра (т. Е. Реального сопоставления с шаблоном регулярного выражения), вы можете использовать upper
вместо этого:
# Yes, this class method is still a scope.
def self.by_templates(templates)
joins(:template).where('upper(templates.label) = any(array[?])', templates.map(&:upcase) }
end
Затем вы можете добавить индекс к templates
на upper(label)
, чтобы ускорить процесс и избежать возможных проблем с случайными метасимволами регулярных выражений в templates
.Я склонен использовать верхний регистр для такого рода вещей из-за странностей, лежащих 'ß'.upcase
, являющихся 'SS'
, но 'SS'.downcase
, являющихся 'ss'
.