ActiveRecord Rails 4, как посмотреть, содержит ли атрибут массива какое-либо из значений в массиве - PullRequest
1 голос
/ 21 января 2020

Скажем, у меня есть модель Book, у которой есть атрибут category, который является массивом. Я хочу создать область, в которой я могу получить все книги, содержащие хотя бы один элемент, из другого массива, в который я хочу передать.

После тщательного поиска в Google и проверки множества различных запросов, самый близкий из найденных мной это:

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

Как я могу заменить 'Mystery' на что-то вроде ['Categ1', 'Categ2', etc...], чтобы я мог получить любую книгу, содержащую, по крайней мере, ОДИН из значений в массиве?

1 Ответ

3 голосов
/ 21 января 2020

Вам нужно знать три вещи:

  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) }

в зависимости о том, как вы хотите использовать прицел.

...