Rails, Ransack: Jak wyszukiwać relacje HABTM dla „wszystkich” meczów zamiast „dowolnych”

Zastanawiam się, czy ktoś ma doświadczenie w używaniu Ransack z relacjami HABTM. Moja aplikacja maphotos które mają relację habtmterms (terminy są jak znaczniki). Oto uproszczone wyjaśnienie tego, czego doświadczam:

Mam dwa zdjęcia: zdjęcie 1 i zdjęcie 2. Mają następujące terminy:

Zdjęcie 1: A, B, C

Zdjęcie 2: A, B, D

Zbudowałem formularz okupu i zaznaczam pola wyboru w formularzu wyszukiwania dla wszystkich terminów, takich jak:

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

Jeśli używam:q[terms_id_in][] i sprawdzam „A, C” moje wyniki to zdjęcie 1 i zdjęcie 2. Chcę tylko zdjęcie 1, ponieważ poprosiłem o A i C, w tym zapytaniu nie obchodzi mnie B ani D, ale chcę zarówno A, jak i C być obecnym na danym wyniku.

Jeśli używamq[terms_id_in_all][] moje wyniki są zerowe, ponieważ żadne zdjęcie nie zawiera tylko A i C. Lub może dlatego, że na jedno połączenie przypada tylko jeden termin, więc żadne połączenie nie pasuje zarówno do A, jak i C. Niezależnie od tego chcę zwrócić tylko zdjęcie 1.

Jeśli używam jakiejkolwiek odmianyq[terms_id_eq][] Nigdy nie otrzymuję żadnych wyników, więc nie sądzę, żeby to działało w tym przypadku.

Tak więc, biorąc pod uwagę połączenie habtm, jak szukać modeli, które pasują do podanych wartości, ignorując nie podane wartości?

Albo, w przypadku jakichkolwiek guru / szyn nie znających Ransacka, jak inaczej mógłbyś stworzyć formularz wyszukiwania, jak opisuję model z połączeniem habtm?

Aktualizacja: zaodpowiedź na powiązane pytanie, Teraz doszedłem do skonstruowania zapytania Arel, które poprawnie pasuje do tego. W jakiś sposób powinieneś być w stanie używać węzłów Arel jako ransackerów, lub jak wskazywali cdesrosiers, jako predykaty niestandardowe, ale jak dotąd nie działałem.

Zgodnie z tą odpowiedzią ustawiam następujący inicjator okupu:

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

... a następnie skonfiguruj następującą metodę na zdjęciu:

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

Niestety to nie działa. Podczasterms_subquery tworzy poprawny SQL, wynikPhoto.search(:has_terms => [2,5]).result.to_sql jest tylko"SELECT \"photos\".* FROM \"photos\" "

questionAnswers(1)

yourAnswerToTheQuestion