質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

Q&A

解決済

1回答

2532閲覧

ransackを使用した複数カラムへの複数ワード検索について

baby_wing

総合スコア11

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

検索

検索は、あるデータの集まりの中から 目的のデータを見つけ出すことです。

0グッド

0クリップ

投稿2020/10/29 09:08

編集2020/10/29 09:49

ransackを使用した検索フォームを作成し、スペース区切りで複数ワードの検索を実現したいと考えています。
「複数ワードを単一カラムから検索」または「単一ワードを複数カラムから検索」であればできるのですが、「複数ワードを複数カラムから検索」をすることができません。過去に質問されていた方の回答を参考にしてみましたが、スペース区切りで分離する前のSQLが再発行されて上書きされてしまいます。if文で分岐を作ってみたりもしましたが、うまくいきません。どなたかご教授願えないでしょうか

controller

1before_action :set_search 2 3 def set_search 4 @categories = Category.where(ancestry: nil) 5 if params[:q].present? 6 if params[:q][:title_or_body_or_material_cont_any] != nil 7 texts = params[:q][:title_or_body_or_material_cont_any].split(/[\p{blank}\s]+/) 8 if texts.size >= 2 #複数ワードかどうかの分岐をしないと単一ワードの場合でエラー発生 9 text_queries = texts.map do |text| 10 Recipe.ransack(title_or_body_or_material_cont_any: text).result 11 end 12 text_queries = text_queries.inject{ |scope, query| scope & query } 13 @search = text_queries.inject{ |scope, query| scope.merge(query)} #(title or body or material) and (title or body or material) 14 @search_recipes = @search #「.page(params[:page]).per(8)」をつけるとエラーになる 15 @text_queries = text_queries #中身の確認用 16 end 17 end 18 @search = Recipe.ransack(params[:q]) #おそらくここでSQLの上書きが発生? 19 @search_recipes = @search.result.page(params[:page]).per(8) 20 else 21 params[:q] = { sorts: 'created_at desc'} 22 @search = Recipe.ransack() 23 @search_recipes = @search.result.page(params[:page]).per(8) 24 end 25 end

試行錯誤しているため、滅茶苦茶なソースですが簡潔な書き方も併せて教えて頂けたら幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こういうややこしいときは普通の検索とRansackを組み合わせています。

まず@q = Recipe.ransack(params[:q]) しますが、これは結果表示画面で検索条件を再表示するためだけに使い、検索には使いません。

title_or_body_or_material_cont_any = params[:q].delete(:title_or_body_or_material_cont_any)
して、title_or_body_or_material_cont_anyを用いて検索条件を作ります
relation = Recipe.[title_or_body_or_material_cont_anyを用いて検索条件] @search_recipes = relation.result.page(params[:page]).per(8)
で得ます

追記
@categories = Category.where(ancestry: nil) if params[:q].present? else の間を変えます。

@categories = Category.where(ancestry: nil) @q = Recipe.ransack(params[:q]) if params[:q].present? if t_b_m_m = params[:q].delete(:title_or_body_or_material_cont_any) relation = Recipe.where() # ここで t_b_m_m を使って relation = Recipe.where().where() という形を # 組んでください。無論 scopeを使っても良いです。 else relation = Recipe end @search = Rrelation.ransack(params[:q]) @search_recipes = @search.result.page(params[:page]).per(8) else

投稿2020/10/29 13:28

編集2020/10/30 23:20
winterboum

総合スコア23329

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

baby_wing

2020/10/30 14:49

回答ありがとうございます。返信が遅くなり申し訳ありません。 初心者なので知識がなくて申し訳ないのですが、`delete`で一度消去するのでしょうか? 回答いただいた内容に変更しようとしたのですが、どこをどう変えればいいのかわかっていない状態です。申し訳ないのですが、よろしければ詳しく教えて頂けないでしょうか
baby_wing

2020/10/31 17:18

where句の作成に少し手間取ってしまいましたが、教えて頂いた方法で実現できました! 丁寧に教えてくださり、ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問