本文介绍了Rails,Ransack:如何在HABTM关系中搜索“全部"内容.匹配而不是“任何"匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否有人有使用Ransack与HABTM关系的经验.我的应用程序具有photos,它与terms有着habtm关系(术语类似于标签).这是我正在经历的简化解释:

I'm wondering if anyone has experience using Ransack with HABTM relationships. My app has photos which have a habtm relationship with terms (terms are like tags). Here's a simplified explanation of what I'm experiencing:

我有两张照片:照片1和照片2.它们具有以下术语:

I have two photos: Photo 1 and Photo 2. They have the following terms:

照片1:A,B,C

照片2:A,B,D

我建立了一个搜袋表单,并在搜索表单中为所有术语打了一个复选框,就像这样:

I built a ransack form, and I make checkboxes in the search form for all the terms, like so:

- 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都出现在给定的结果中.

If I use: q[terms_id_in][] and I check "A, C" my results are Photo 1 and Photo 2. I only want Photo 1, because I asked for A and C, in this query I don't care about B or D but I want both A and C to be present on a given result.

如果我使用q[terms_id_in_all][],则结果为nil,因为两张照片都不包含A和C.或者,也许因为每个联接只包含一个术语,所以没有联接同时匹配A和C.无论如何,我只需要Photo 1个要退回.

If I use q[terms_id_in_all][] my results are nil, because neither photo includes only A and C. Or, perhaps, because there's only one term per join, so no join matches both A and C. Regardless, I want just Photo 1 to be returned.

如果我使用各种q[terms_id_eq][],我都不会得到任何结果,因此我认为在这种情况下不起作用.

If I use any variety of q[terms_id_eq][] I never get any results, so I don't think that works in this case.

因此,在存在habtm连接的情况下,如何在不考虑未给定值的情况下搜索与给定值匹配的模型?

So, given a habtm join, how do you search for models that match the given values while ignoring not given values?

或者,对于不熟悉Ransack的所有Rails/sql专家,您还可以如何创建一个搜索表单,例如我正在为具有habtm连接的模型描述的那样?

Or, for any rails/sql gurus not familiar with Ransack, how else might you go about creating a search form like I'm describing for a model with a habtm join?

更新:根据相关问题的答案,现在,我已经构建了一个与之正确匹配的Arel查询.您应该能够以某种方式将Arel节点用作掠夺者或cdesrosiers指出的自定义谓词,但到目前为止,我还没有使用它.

Update: per the answer to related question, I've now gotten as far as constructing an Arel query that correctly matches this. Somehow you're supposed to be able to use Arel nodes as ransackers, or as cdesrosiers pointed out, as custom predicates, but thus far I haven't gotten that working.

根据该答案,我设置了以下ransack初始化程序:

Per that answer, I setup the following ransack initializer:

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

...,然后在照片上设置以下方法:

... and then setup the following method on 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的结果仅为"SELECT \"photos\".* FROM \"photos\" "

Unfortunately this doesn't seem to work. While terms_subquery produces the correct SQL, the result of Photo.search(:has_terms => [2,5]).result.to_sql is just "SELECT \"photos\".* FROM \"photos\" "

推荐答案

使用在我的 answer 对于您的相关问题,这应该可以对您的标记进行简单的更改:

With a custom ransack predicate defined as in my answer to your related question, this should work with a simple change to your markup:

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


更新


UPDATE

:formatter并没有按照我的想法做,并且由于Ransack存储库没有提及子查询",您可能无法将其用于您想做的事,之后全部.所有可用的选项似乎都已用尽,因此只剩下猴子补丁了.

The :formatter doesn't do what I thought, and seeing as how the Ransack repo makes not a single mention of "subquery," you may not be able to use it for what you're trying to do, after all. All available options seem to be exhausted, so there would be nothing left to do but monkey patch.

为什么不像过去通常使用活动记录(甚至使用现在的Arel查询)那样,不跳过搜票并查询照片"表?您已经知道查询有效.您希望从使用Ransack中学到什么好处?

Why not just skip ransack and query the "photos" table as you normally would with active record (or even with the Arel query you now have)? You already know the query works. Is there a specific benefit you hoped to reap from using Ransack?

这篇关于Rails,Ransack:如何在HABTM关系中搜索“全部"内容.匹配而不是“任何"匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 11:54