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

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

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

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Q&A

1回答

236閲覧

レコード取得の記述をもっと綺麗に書きたい

rnanayo

総合スコア0

Ruby on Rails 5

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

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

0グッド

1クリップ

投稿2022/05/10 11:58

前提

フォームで入力された条件で、レコードの検索をかけるときにフォームの各項目に値があるかどうかでwhere文が変わります。
当初は、各項目を必須にすることはできないため、すべてのwhere文でワイルドカードであいまい検索を行っていました。
そうすると、処理が重くなってしまうため各項目の有無によってwhere文をわけるようにしました。

フォーム内容を必須にすることは考えていません。

実現したいこと

もう少し、簡潔に記述できるのではないかと思っているのですが、その方法があれば教えていただきたいです。

該当のソースコード

/model/history.rb

ruby

1def self.find_records(params) 2 logger.info(params) 3 4 shop_name = params[:shop].present? ? params[:shop] : '' 5 start_time = params[:start_time] 6 end_time = params[:end_time] 7 first_name = params[:first_name].present? ? params[:first_name] : '' 8 last_name = params[:last_name].present? ? params[:last_name] : '' 9 status = params[:status].present? ? params[:status] : '' 10 11 production_flg = (params[:first_name].present? && params[:last_name].present?) == true ? true : false 12 13 # shop_id、status、prodction 14 if shop_id != '' && status != '' && production_flg 15 record = 16 self.joins(:shop, :production) 17 .select('histories.*, productions.first_name, productions.last_name, shops.name') 18 .where("first_name = ?", "#{first_name}") 19 .where("last_name = ?", "#{last_name}") 20 .where("name = ?", "#{shop_name}") 21 .where("status = ?", "#{status}") 22 .where("start_time BETWEEN '#{start_time}' and '#{end_time}'") 23 .order("start_time") 24 # shop_id, status 25 elsif shop_id != '' && status != '' 26 record = 27 self.joins(:shop, :production) 28 .select('histories.*, productions.first_name, productions.last_name, shops.name') 29 .where("first_name LIKE ?", "%#{first_name}%") 30 .where("last_name LIKE ?", "%#{last_name}%") 31 .where("name = ?", "#{shop_name}") 32 .where("status = ?", "#{status}") 33 .where("start_time BETWEEN '#{start_time}' and '#{end_time}'") 34 .order("start_time") 35 # shop_id 36 elsif shop_id != '' 37 record = 38 self.joins(:shop, :production) 39 .select('histories.*, productions.first_name, productions.last_name, shops.name') 40 .where("first_name LIKE ?", "%#{first_name}%") 41 .where("last_name LIKE ?", "%#{last_name}%") 42 .where("name = ?", "#{shop_name}") 43 .where("status LIKE ?", "%#{status}%") 44 .where("start_time BETWEEN '#{start_time}' and '#{end_time}'") 45 .order("start_time") 46 else 47 record = 48 self.joins(:shop, :production) 49 .select('histories.*, production.first_name, production.last_name, shops.name') 50 .where("first_name LIKE ?", "%#{first_name}%") 51 .where("last_name LIKE ?", "%#{last_name}%") 52 .where("name LIKE ?", "%#{shop_name}%") 53 .where("status LIKE ?", "%#{status}%") 54 .where("start_time BETWEEN '#{start_time}' and '#{end_time}'") 55 .order("start_time") 56 end 57 return record 58 end 59

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

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

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

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

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

guest

回答1

0

if文を使った検索条件の組み立て

検索条件が入力されたときだけ where を追加したい場合、if を使って以下のように書くことができます。

rb

1# 共通部分は先頭でまとめて指定 2records = self.joins(:shop, :production) 3 .select('histories.*, ... , shops.name') 4 .order(:start_time) 5 6# 送付されたパラメータに応じて where を追加 7if xxxx 8 records = records.where("xxxx = ?", xxxx) 9end 10 11if yyyy 12 records = records.where("yyyy = ?", yyyy) 13end 14 15if zzzz 16 records = records.where("zzzz = ?", zzzz) 17end 18 19return records

これを使うと、パラメータが一部だけ指定された場合でも、すべて指定された場合でも、同じコードで処理できます。
production_flgLIKE を一通りコードから除去できるはずです。

rb

1# ------------------------------------------ 2# 修正前 3# ------------------------------------------ 4 5 production_flg = params[:first_name].present? && params[:last_name].present? 6 7 if production_flg 8 record = self.joins(...) 9 .select(...) 10 .where("first_name = ?", "#{first_name}") 11 .where("last_name = ?", "#{last_name}") 12 .order(...) 13 else 14 record = self.joins(...) 15 .select(...) 16 .where("first_name LIKE ?", "%#{first_name}%") 17 .where("last_name LIKE ?", "%#{last_name}%") 18 .order(...) 19 end 20 return record 21 22 23# ------------------------------------------ 24# 修正後 25# ------------------------------------------ 26 27 records = self.joins(...) 28 .select(...) 29 .order(...) 30 31 if params[:first_name].present? 32 records = records.where("first_name = ?", params[:first_name]) 33 end 34 35 if params[:last_name].present? 36 records = records.where("last_name = ?", params[:last_name]) 37 end 38 39 return records

範囲指定系の検索条件の組み立て

現状のコードでは start_time と end_time を BETWEEN で処理されていますが、どちらか片方だけ指定された場合に備えて <=>= に分解した方が良いです。

rb

1# ------------------------------------------ 2# 修正前 3# ------------------------------------------ 4 5 record = ... 6 .where("start_time BETWEEN '#{start_time}' and '#{end_time}'") 7 8 9# ------------------------------------------ 10# 修正後 11# ------------------------------------------ 12 13 if params[:start_time].present? 14 records = records.where("start_time >= ?", params[:start_time]) 15 end 16 17 if params[:end_time].present? 18 records = records.where("start_time <= ?", params[:end_time]) 19 end

後置if

人により好みが分かれますが、 後置ifを使うと更にコードをコンパクトにできます。

diff

1- if xxxx 2- records = records.where("xxxx = ?", xxxx) 3- end 4 5+ records = records.where("xxxx = ?", xxxx) if xxxx

最終的なコード

rb

1def self.find_records(params) 2 logger.info(params) 3 4 records = self.joins(:shop, :production) 5 .select('histories.*, productions.first_name, productions.last_name, shops.name') 6 .order(:start_time) 7 8 records = records.where("name = ?", params[:shop]) if params[:shop].present? 9 records = records.where("start_time >= ?", params[:start_time]) if params[:start_time].present? 10 records = records.where("start_time <= ?", params[:end_time]) if params[:end_time].present? 11 records = records.where("first_name = ?", params[:first_name]) if params[:first_name].present? 12 records = records.where("last_name = ?", params[:last_name]) if params[:last_name].present? 13 records = records.where("status = ?", params[:status]) if params[:status].present? 14 15 return records 16end

投稿2022/05/17 03:24

shinoharat

総合スコア1676

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問