6

一个基本问题,但我在项目页面wiki中找不到明确的内容。我有以下代码:

field = "secre"
Position.search( {:description_cont => field, :code_cont => field}).result(:distinct => true).to_sql
 => "SELECT DISTINCT `positions`.* FROM `positions`  WHERE ((`positions`.`description` LIKE '%secre%' AND `positions`.`code` LIKE 0))"

但我的查询应该是这样的:

 => "SELECT DISTINCT `positions`.* FROM `positions`  WHERE ((`positions`.`description` LIKE '%secre%' OR `positions`.`code` LIKE 0))"

任何帮助,将不胜感激。提前致谢

4

5 回答 5

4

尝试以下操作:

Position.search( {:description_or_code_cont => field}).result(:distinct => true).to_sql
于 2013-01-04T17:52:45.770 回答
1

这可能不是您问题的确切答案,但是因为我自己用谷歌搜索了在 Ransack 中进行 OR 搜索的正确方法,但没有找到好的答案,但我自己设法解决了问题,我想我d 分享解决方案。

在我正在处理的应用程序中,有一个搜索页面,它将模型的各个字段Customer(链接到 DB 表customers)作为参数,然后列出与搜索结果匹配的那些客户的表。客户拥有三个不同的电话号码字段,并且之前的搜索页面对每种类型的号码都有不同的搜索字段。我想将它们组合到一个字段中,以便在所有数字中方便地搜索。

数据库有这三个字段定义(在这些片段中,我只更改了一些标识符名称):

mysql> desc customers;
+--------------------------+------------------+------+-----+---------+----------------+
| Field                    | Type             | Null | Key | Default | Extra          |
+--------------------------+------------------+------+-----+---------+----------------+
...
| customer_phone_a         | varchar(50)      | YES  |     | NULL    |                |
| customer_phone_b         | varchar(50)      | YES  |     | NULL    |                |
| customer_phone_c         | varchar(50)      | YES  |     | NULL    |                |
+--------------------------+------------------+------+-----+---------+----------------+

以前,搜索页面(文件app/views/customers/index.html.erb)包含以下内容:

<%= search_form_for @search do |f| %> <!-- this is a Ransack-provided form -->
  <div class="field">
...
    <%= f.label :customer_phone_a_spaces_match_anything, "Phone number A is or contains:" %>
    <%= f.text_field :customer_phone_a_spaces_match_anything %>

    <%= f.label :customer_phone_b_spaces_match_anything, "Phone number B is or contains:" %>
    <%= f.text_field :customer_phone_b_spaces_match_anything %>

    <%= f.label :customer_phone_c_spaces_match_anything, "Phone number C is or contains:" %>
    <%= f.text_field :customer_phone_c_spaces_match_anything %>
...
  </div>

  <div class="actions">
    <%= f.submit "Search", class: "btn btn-large btn-primary" %>
  </div>

<% end %> <!-- search_form_for -->

(这与现在无关,但文件的内容config/initializers/ransack.rb是:

Ransack.configure do |config|

  config.add_predicate 'spaces_match_anything',
  :arel_predicate => 'matches', # so we can use the SQL wildcard "%"
  # Format the incoming value: add the SQL wildcard character "%" to the beginning and the end of
  # the string, replace spaces by "%", and replace multiple occurrences of "%" by a single "%".
  :formatter => proc {|v| ("%"+v.gsub(" ", "%")+"%").squeeze("%")}

end

这意味着除了 Ransack 的默认eq,cont等之外,我还可以spaces_match_anything在搜索中使用我的自定义谓词。谓词做它所说的。)

无论如何,从您所做的同一个示例中获得灵感,我将以下 ransacker 添加到模型中app/models/customer.rb

ransacker :all_phones do |parent|
  Arel::Nodes::InfixOperation.new('||',
    Arel::Nodes::InfixOperation.new('||',
      Arel::Nodes::InfixOperation.new('||', parent.table[:customer_phone_a]||"", ' '),
                                    parent.table[:customer_phone_b]||"", ' '),
                                  parent.table[:customer_phone_c]||"")
end

最后,我将搜索页面中的三个电话号码搜索字段替换为:

<%= f.label :customer_phone_a_or_customer_phone_b_or_customer_phone_c_cont, "Phone number is or contains:" %>
<%= f.text_field :customer_phone_a_or_customer_phone_b_or_customer_phone_c_cont %>

用户在此搜索字段中输入的数字现在将匹配客户的三个数字中的任何一个。(请注意在 ransacker 中对空数 , 的防范||""。)

这经过测试可与 Ruby v1.9.3 和 Rails v3.2.8 一起使用。输入参数将不匹配一个数字的结尾和下一个数字的开头,即使在正确的位置输入空格也不匹配,即使在搜索字段代码中,我替换_cont_spaces_match_anything

于 2012-11-20T15:46:29.503 回答
1

把它放在你的 search_form_for 标签下。这是假设您使用的是 f:

<%= f.combinator_select %>

它将生成一个带有两个选项的选择。全部或任何。ANY 将使用 OR 子句。ALL 将使用 AND 子句。

于 2013-12-05T21:54:01.513 回答
1

现在我们可以很简单地使用 or-query 和 ransack:

Position.ransack(description: 'secret').result.or(Position.ransack(code: 0).result)
于 2019-11-21T12:01:57.093 回答
0

在深入研究了Ransack 演示代码之后,我做了如下操作:

field = "secre"
q= {
  "m"=>"or", 
  "c"=>{
    "0"=>{
      "a"=>{
        "0"=>{
          "name"=>"description"
        }
      }, 
      "p"=>"cont", 
      "v"=>{
        "0"=>{
          "value"=>field
        }
      }
    }, 
    "1"=>{
      "a"=>{
        "0"=>{
          "name"=>"code"
        }
      }, 
      "p"=>"cont", 
      "v"=>{
        "0"=>{
          "value"=>field
        }
      }
    }
  }
}
Position.search(q).result(:distinct => true).to_sql
 => "SELECT DISTINCT `positions`.* FROM `positions`  WHERE ((`positions`.`description` LIKE '%secre%' OR `positions`.`code` LIKE 0))"

是的,这很恶心,当然这不应该是最好的方法,但它暂时救了我。还有其他想法吗?

于 2012-10-17T20:09:38.250 回答