Rails, Ransack: Как искать отношения HABTM для «всех» совпадений вместо «любых»

Мне интересно, есть ли у кого-нибудь опыт использования Ransack с HABTM-связями. Мое приложение имеетphotos которые имеют отношения habtm сterms (термины похожи на теги). Вот упрощенное объяснение того, что я испытываю:

У меня есть две фотографии: Фото 1 и Фото 2. Они имеют следующие условия:

Фото 1: А, Б, В

Фото 2: A, B, D

Я построил форму для разграбления, и я делаю флажки в форме поиска для всех терминов, например так:

- terms.each do |t|
  = check_box_tag 'q[terms_id_in][]', t.id

Если я использую:q[terms_id_in][] и я проверяю «A, C», мои результаты - Фото 1 и Фото 2. Я хочу только Фото 1, потому что я попросил A и C, в этом запросе мне нет дела до B или D, но я хочу и A, и C присутствовать на данном результате.

Если я используюq[terms_id_in_all][] мои результаты равны нулю, потому что ни одна фотография не включает в себя только А и С. Или, возможно, потому, что в соединении есть только один термин, поэтому объединение не соответствует ни А, ни С. Независимо от того, я хочу, чтобы была возвращена только фотография 1.

Если я использую любое разнообразиеq[terms_id_eq][] Я никогда не получаю никаких результатов, поэтому я не думаю, что это работает в этом случае.

Итак, учитывая соединение habtm, как вы будете искать модели, которые соответствуют заданным значениям, игнорируя при этом не заданные значения?

Или, для любых rails / sql гуру, не знакомых с Ransack, как еще вы могли бы создать форму поиска, как я описываю для модели с habtm соединением?

Обновление: заответ на связанный вопросТеперь я дошел до построения запроса Arel, который правильно соответствует этому. Каким-то образом вы должны иметь возможность использовать узлы Arel в качестве вымогателей или, как указали кадры, в качестве пользовательских предикатов, но до сих пор я не получил эту работу.

Для этого ответа я установил следующий инициализатор Ransack:

Ransack.configure do |config|
  config.add_predicate 'has_terms',
    :arel_predicate => 'in',
    :formatter => proc {|term_ids| Photo.terms_subquery(term_ids)},
    :validator => proc {|v| v.present?},
    :compounds => true
end

... и затем настройте следующий метод на Фото:

def self.terms_subquery(term_ids)
  photos = Arel::Table.new(:photos)
  terms = Arel::Table.new(:terms)
  photos_terms = Arel::Table.new(:photos_terms)
  photos[:id].in(
  photos.project(photos[:id])
    .join(photos_terms).on(photos[:id].eq(photos_terms[:photo_id]))
    .join(terms).on(photos_terms[:term_id].eq(terms[:id]))
    .where(terms[:id].in(term_ids))
    .group(photos.columns)
    .having(terms[:id].count.eq(term_ids.length))
  ).to_sql
end

К сожалению, это не похоже на работу. Покаterms_subquery выдает правильный SQL, результатPhoto.search(:has_terms => [2,5]).result.to_sql просто"SELECT \"photos\".* FROM \"photos\" "

Ответы на вопрос(1)

Ваш ответ на вопрос