ransackのgithub↓
はじめに
今回はrailsのransackというgemを使用して、検索機能を作成していこうと思います。そして、この検索機能を作成する際には、これ専用の簡単なアプリケーションを使用しようと思います。
1.アプリケーションの準備をする
①アプリケーションの雛形を作る
rails new ransack
②scaffoldを使用してユーザのモデルを作成する
rails g scaffold User name:string age:integer height:integer weight:integer gender:string
rails db:migrate
※scaffoldはテンプレートとなるファイルを全て自動で作成してくれる。
③データベースに初期データを追加する
users = [
{ name: '田中ゆうこ', age: 24, height: 155, weight: 40, gender: '女' },
{ name: '山田花子', age: 19, height: 150, weight: 39, gender: '女' },
{ name: '田中太郎', age: 20, height: 160, weight: 45, gender: '男' },
{ name: '森山太郎', age: 26, height: 167, weight: 60, gender: '男' },
{ name: '山田太郎', age: 34, height: 175, weight: 74, gender: '男' },
{ name: '秋山なお', age: 18, height: 160, weight: 46, gender: '女' }
]
User.create(users)
rails db:seed
ここまででようやく準備が整いました!次からはransackについてをやっていきましょう。
2.ransackを導入する
gem 'ransack'
bundle install
ここでサーバーを起動して、localhost:3000/usersにアクセスすると、
このようなページが表示されるようになる。
このページは自分でroutesなどを書いていなかったとしてもscaffoldで自動的に作成されている。
3.検索をするためのアクションを追加する
①routesファイルの編集
Rails.application.routes.draw do
resources :users do
collection do
get 'search'
end
end
end
検索をして、その結果を表示するためのアクションsearchを追加する。
②コントローラにsearchアクションを定義する
class UsersController < ApplicationController
before_action :set_user, only: %i[ show edit update destroy ]
def search
@q = User.ransack(params[:q])
@results = @q.result
end
# GET /users or /users.json
def index
@q = User.ransack(params[:q])
@users = User.all
end
# GET /users/1 or /users/1.json
def show
end
# GET /users/new
def new
@user = User.new
end
# GET /users/1/edit
def edit
end
# POST /users or /users.json
def create
@user = User.new(user_params)
respond_to do |format|
if @user.save
format.html { redirect_to user_url(@user), notice: "User was successfully created." }
format.json { render :show, status: :created, location: @user }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1 or /users/1.json
def update
respond_to do |format|
if @user.update(user_params)
format.html { redirect_to user_url(@user), notice: "User was successfully updated." }
format.json { render :show, status: :ok, location: @user }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1 or /users/1.json
def destroy
@user.destroy
respond_to do |format|
format.html { redirect_to users_url, notice: "User was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user
@user = User.find(params[:id])
end
# Only allow a list of trusted parameters through.
def user_params
params.require(:user).permit(:name, :age, :height, :weight, :gender)
end
end
ここでsearchアクションを定義し、その中でransackを使用していきます。indexの中で検索フォームを作成するため、indexの中にもransackを用いた変数を定義します。
③検索フォームの作成
次はindex.html.erbの一番下に検索フォームを作成していきます。
<h1>ユーザー検索</h1>
<%= search_form_for @q, url: search_users_path do |f| %>
<%= f.label :name_cont, 'ユーザー名' %>
<%= f.search_field :name_cont %>
<br>
<%= f.submit '検索' %>
<% end %>
ひとまずはこんな感じで作ってみます。ここで使用されているsearch_form_forはransackに標準で用意されているフォームメソッドです。form_forやform_withなどを普段のフォームで使用すると思いますが、そのransack版となっています。
search_fieldでは元々userモデルの中にあるnameに_contと記述していますが、これは部分検索をする際に使用するメソッドです。他にも_contの部分を_eqに変更すると、完全一致のものが検索できるようになるなど、さまざまなメソッドが用意されています。
④検索結果を表示するviewを作成する
フォームを作っただけだと、検索結果を表示させることができません。なので、検索結果を表示させるためのviewを作っていきます。views/usersの中にsearch.html.erbを新しく作成してその中に検索結果の出力を記述していきます。
<h1>検索結果</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Height</th>
<th>Weight</th>
<th>Gender</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @results.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.age %></td>
<td><%= user.height %></td>
<td><%= user.weight %></td>
<td><%= user.gender %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<%= link_to 'Top', users_path %>
このように記述をすることができたら、サーバーを起動して挙動を確認していきます。
このように検索・検索結果の出力をすることができました。
⑤フォームを書き換えてみる
<h1>ユーザー検索</h1>
<%= search_form_for @q, url: search_users_path do |f| %>
<%= f.label :name_cont, 'ユーザー名' %>
<%= f.search_field :name_cont %>
<%= f.label :age, '年齢' %>
<%= f.radio_button :age_lteq, '' %>指定しない
<%= f.radio_button :age_lteq, '10' %>10歳以下
<%= f.radio_button :age_lteq, '20' %>20歳以下
<%= f.radio_button :age_lteq, '30' %>30歳以下
<%= f.radio_button :age_lteq, '40' %>40歳以下
<%= f.radio_button :age_gteq, '50' %>50歳以上
<br>
<%= f.submit '検索' %>
<% end %>
フォームの部分を書き換えてみると、名前での検索もでき、名前と年齢での検索もでき、年齢での検索もできる検索フォームを作成することができます。
4.ソート機能を作成する
このransackを使用すると、並び替えの機能も簡単に実装することができるので、そちらについても解説していきます。
①indexのカラム名を変更
<th><%= sort_link(@q, :name, "Name") %></th>
<th><%= sort_link(@q, :age, "Age") %></th>
<th><%= sort_link(@q, :height, "Height") %></th>
<th><%= sort_link(@q, :weight, "Weight") %></th>
<th><%= sort_link(@q, :gender, "Gender") %></th>
②検索結果のカラム名を変更
<th><%= sort_link(@q, :name, "Name") %></th>
<th><%= sort_link(@q, :age, "Age") %></th>
<th><%= sort_link(@q, :height, "Height") %></th>
<th><%= sort_link(@q, :weight, "Weight") %></th>
<th><%= sort_link(@q, :gender, "Gender") %></th>
③indexアクションを編集
今のままでは検索結果のページではソートすることが可能ですが、indexページでのソートができないので、できるようにindexアクションの@usersの部分を編集していきます。
# GET /users or /users.json
def index
@q = User.ransack(params[:q])
@users = @q.result
end
これでソート機能を実装することができました。
④ソート時の矢印を消してみる
ソートをするリンクを踏んだ際に上矢印や下矢印が出てきて、どちらのソートかわかりやすいようになってはいますが、レイアウトによってはない方がいいかもしれません。なので、この矢印を消す方法をやってみます。
<th><%= sort_link(@q, :name, "Name", hide_indicator: true) %></th>
<th><%= sort_link(@q, :age, "Age", hide_indicator: true) %></th>
<th><%= sort_link(@q, :height, "Height", hide_indicator: true) %></th>
<th><%= sort_link(@q, :weight, "Weight", hide_indicator: true) %></th>
<th><%= sort_link(@q, :gender, "Gender", hide_indicator: true) %></th>
はい。ただhide_indicator:trueをつけただけです。超簡単!
おわり
今回はransackを使った検索機能を別のアプリケーションを作成して実装してみました。
ransackはとても便利に検索機能を実装できますね。ですけど、検索機能だけではなく、パラメータの渡し方を勉強したいみたいな人はransackを使わない方法で実装してみてからransackを実装していただくと、実装の簡単さにも驚かされますし、色々な学習にもなるかなと感じました。
最後まで読んでいただきありがとうございます!また別の記事でお会いしましょう!