環境
Ruby 3.0.0
Rails 6.1.4.4
ransack 2.5.0
enum_help
何ができるようになるか
上記の画像のようにタスクをタスク名とステータスからAND検索できるようになる。
また、ステータスはenumを使って表現できるようになる。
手順
①enumを導入する
ここでは、name(タスク名)を持つTaskモデルにstatus(タスクのステータス)カラムを追加します。
今回は、Taskモデルに未着手
、着手中
、完了
の3つのステータスを持たせることにします。
その場合、statusにそのまま文字列で保存するやり方もあるのですが、それだと効率が悪いためActiveRecordの機能であるenum
を使用して、それぞれのstatusに数値を与えることとします。
not_started_yet: 0,
under_start: 1,
completion: 2
まずはmigrarionファイルの作成です。
% rails g migration AddStatusToTasks status:integer
statusは数値を保存するため、integer
型とします。
カラムを追加したら、enumクラスメソッドにカラム名、対応する値を定義します。
class Task < ApplicationRecord
(略)
enum status: {
not_started_yet: 0,
under_start: 1,
completion: 2
}
end
これで、enumの設定は完了です。
②enumの日本語化
次に先ほど定義したシンボルを日本語化します。
日本語化には、enum_help
というgemが便利です。
gem 'enum_help' をGemfileに追加
% bundle install
gemをインストールしたら、locales/ja.ymlに日本語訳を記述していきます。
ja:
enums:
task:
status:
not_started_yet: "未着手"
under_start: "着手中"
completion: "完了"
参考: https://github.com/zmbacker/enum_help
③ransackを使って検索機能の実装
ransackを使うことで検索機能を簡単に実装することができます。
gem 'ransack' をGemfileに追記
% bundle install
先にコントローラの完成形を記します。
class TasksController < ApplicationController
before_action :set_q, only: [:index, :search]
def index
@statuses = Task.statuses_i18n
end
def search
@tasks = @q.result(distinct: true)
end
private
def set_q
@q = Task.ransack(params[:q])
end
end
ここでは、set_q
アクションで送られてきたパラメータを元にransackがデータの検索を行います。
そのデータがsearch
アクションにてActiveRecord形式に変換され、@tasks
に格納されます。
次にviewを記します。
<%= search_form_for @q, url: search_tasks_path do |f| %>
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<% @statuses.each do |status| %>
<%= f.check_box :status_eq_any, { multiple: true, include_hidden: false }, status[0] %>
<%= f.label status[1] %>
<% end %>
<%= f.submit %>
<% end %>
ここでのポイントは検索条件の指定方法です。
何やらname_cont
やstatus_eq_any
のようにカラム名に続く文字が存在しています。
これは検索条件を表しており、
contだと〜の文字列を含む
eq_anyだと完全一致した一つ以上のパラメータ
という意味を持ちます。
参考: https://github.com/activerecord-hackery/ransack#search-matchers
まとめ
gemを使うことで、簡単に検索機能を実装することができました。