これはあなたの質問に対する正確な答えではないかもしれませんが、私は自分でランサックでOR検索を行う正しい方法をグーグルで探し、良い答えを見つけられませんでしたが、自分で問題を解決することができたので、私は思ったdソリューションを共有します。
私が取り組んでいるアプリケーションには、モデルのさまざまなフィールドCustomer
(DBテーブルにリンクされているcustomers
)をパラメーターとして受け取り、検索結果に一致する顧客のテーブルを一覧表示する検索ページがあります。顧客には3つの異なる電話番号フィールドがあり、検索ページには以前は番号のタイプごとに異なる検索フィールドがありました。それらを1つのフィールドにまとめて、すべての数字の中から便利に検索できるようにしたかったのです。
データベースには、次の3つのフィールド定義があります(これらのスニペットでは、一部の識別子名のみを変更しました)。
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
を検索に使用できることを意味します。述語はそれが言うことをします。)
とにかく、あなたがしたのと同じ例からインスピレーションを得て、私はモデルに次のランサッカーを追加しました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
最後に、検索ページの3つの電話番号検索フィールドを次のように置き換えました。
<%= 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 %>
ユーザーがこの検索フィールドに入力する番号は、顧客の3つの番号のいずれかに一致するようになります。(ランサッカーのヌル番号に対するガードに注意してください||""
。)
これは、Rubyv1.9.3およびRailsv3.2.8で動作するようにテストされています。入力パラメータは、スペースが正しい場所に入力されていても、検索フィールドコードにある場合でも、1つの数値の終わりと次の数値の始まりと一致しません。私は。に置き換え_cont
ます_spaces_match_anything
。