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\" "