Rails,Ransack:如何在“所有”匹配中搜索HABTM关系而不是“任何”
我想知道是否有人有使用Ransack与HABTM关系的经验。 我的应用程序的photos
与terms
有关系(术语类似于标签)。 这是我正在经历的简化说明:
我有两张照片:照片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获得特定的好处吗?