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][] и я проверяюА, С " мои результаты - Фото 1 и Фото 2. Я хочу только Фото 1, потому что я попросил А и С, в этом запросе я неМеня не интересуют B или D, но я хочу, чтобы и A, и C присутствовали в данном результате.

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

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

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

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

Обновление: заответ на связанный вопросЯТеперь мы дошли до построения запроса 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)

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