Rails,Ransack:如何在“所有”匹配中搜索HABTM关系而不是“任何”

我想知道是否有人有使用Ransack与HABTM关系的经验。 我的应用程序的photosterms有关系(术语类似于标签)。 这是我正在经历的简化说明:

我有两张照片:照片1和照片2.他们有以下条款:

照片1:A,B,C

照片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][]我的结果是零,因为q[terms_id_in_all][]照片都不包含A和C.或者,也许,因为每个连接只有一个术语,所以没有连接匹配A和C.无论如何,我只想要照片1将被退回。

如果我使用任何种类的q[terms_id_eq][]我从来没有得到任何结果,所以我认为这不适用于这种情况。

因此,给定一个habtm连接,如何在忽略未给定值的同时搜索与给定值匹配的模型?

或者,对于任何不熟悉Ransack的rails / sql专家,你怎么可能去创建一个搜索表单,比如我正在描述一个带有habtm连接的模型?


更新:根据相关问题的答案 ,我现在已经建立了一个正确匹配它的Arel查询。 不知何故,你应该能够使用Arel节点作为搜索者,或者像cdesrosiers所指出的那样,作为自定义谓词,但到目前为止我还没有得到这样的工作。

根据该答案,我设置了以下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 

…然后在Photo上设置以下方法:

 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的结果Photo.search(:has_terms => [2,5]).result.to_sql只是"SELECT \"photos\".* FROM \"photos\" "

使用自定义的ransack谓词定义为我对相关问题的回答,这应该只需对标记进行简单的更改:

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

UPDATE

:formatter没有按照我的想法行事,并且看到Ransack repo如何不提及“子查询”,你可能无法将它用于你想要做的事情,毕竟。 所有可用的选项似乎都已用尽,所以除了猴子补丁之外别无他法。

为什么不像通常使用活动记录那样跳过搜索和查询“照片”表(或者甚至使用现在的Arel查询)? 您已经知道查询有效。 您希望通过使用Ransack获得特定的好处吗?

Interesting Posts