LoginSignup
5
2

More than 3 years have passed since last update.

Rails | 動的ディスパッチを使って検索ロジックを一行にしてみる試み

Posted at

良いこと思いつたと思って、一回これをやって先輩に怒られたので真似しない方がいいです。
ただ自分的に結構おもしろいなあと思ったのでメモ。

概要

株式会社万葉の新入社員教育用カリキュラムのタスク管理アプリを使います。
既に@yokku21 さんが終わらせたものをフォークしてきました(どうもありがとうございました)。

タスク一覧画面では、タスクをタスク名、ステータス、優先度、ラベルで絞り込むことができ、さらにそれらを並び替えることができます。
今回、ここを一行にしてみたいと思います。

プルリク

ビフォーアフター

ビフォー(イメージ)

# app/controllers/tasks_controller.rb

def index
  @tasks = current_user.tasks.with_title(params[:title]).
                              with_status(params[:status]).
                              with_priority(params[:priority]).
                              with_label_ids(params[:label_ids]).
                              sorted_by(params[:sort_option])
end

既にイイ感じに@yokku21さんが仕上げてくれています、、、!

  • 補足:
    • これらのスコープの命名規則はこちらに従っています。
    • スコープをチェーンできるようにblankが来た時はnextを返す処理にしています。

アフター

# app/controllers/tasks_controller.rb

def index
  @tasks = current_user.tasks.filtered_by(filter_params)
end

一行!!ナニコレめっちゃスリム!

解説

1). 検索用フォームのname属性はスコープの名前にしとく

<!-- 例: app/views/tasks/index.html.erb -->

<%= f.text_field(:with_title, ...) %>
<%= f.select(:with_status, ...) %>
<%= f.select(:with_priority, ...) %>
<%= f.select(:with_priority, ...) %>
<%= f.collection_check_boxes(:with_label_ids, ...) %>

2). コントローラにて検索で使うparamsだけを取得できるようにしとく

# 例: app/controllers/tasks_constolle.rb

private

def filter_params
  params.permit(
    :with_title,
    :with_status,
    :with_priority,
    :sorted_by,
    with_label_ids: [],
  ).delete_if{|key, value| value.blank? }.to_h
end

3). スコープの親分を作る

# 例: app/models/task.rb

scope :filtered_by, -> (filter_params) do
  filter_params.inject(self) do |task, param|
    task.send(param[0], param[1])
  end
end

たたみこみ演算と初期値をselfとすることで、チェーンしながらスコープを呼んでいきます。

4). 完成

# app/controllers/tasks_controller.rb

def index
  @tasks = current_user.tasks.filtered_by(filter_params)
end
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2