#Ruby on Rails チュートリアルについて
Ruby on Railsを勉強したいというと、まず紹介される有名なRailsのチュートリアル。
内容はハードですが、無料でRailsによるWebアプリケーション開発を楽しく学べます。
Ruby on Rails チュートリアル
https://railstutorial.jp/
#Sample Appの拡張
チュートリアルの最後には、作成したSampleAppの拡張機能についていくつかのヒントが記載されています。
その中の以下の機能を順に実装していきます(途中で挫折するかも。。。)。
- ユーザー検索
- マイクロポスト検索
- フォロワーの通知
- 返信機能
- メッセージ機能
#ユーザー検索
今回は、1つ目のユーザー検索の実装を行います。
具体的には、全ユーザーを表示するページ(/users)上での、ユーザー名の検索、検索結果の表示を実現します。
##環境と準備
ユーザー検索(および次回のマイクロポスト検索)では、Rails用の検索機能を簡単に実装できるRansack Gemを利用することにします。
Ransackは他のGemと同様に、Gemfileに追加し、bundle installします。
モジュール | バージョン |
---|---|
Rails | 5.1.2 |
Ruby | 2.3.1 |
Ransack | 1.8.4 |
##実装
まず、ユーザー検索用のフォームを作成します。
<%= search_form_for @q do |f| %>
<%= f.label :name_cont, 'User Search' %>
<div class="input-group">
<%= f.text_field :name_cont, placeholder: "Enter username...",
class: 'form-control' %>
<span class="input-group-btn">
<%= f.submit 'Go', class: "btn btn-primary" %>
</span>
</div>
<% end %>
上記のコードでは、「:name_cont」を利用しています。
今回の検索では、ユーザー名(name)に検索ワードが含まれているか(cont、containのこと)を調べるため、「:name_cont」を指定しています。
このフォームは後ほどindex.html.erbに組み込みます。
次に、UsersContorollerのindexアクションに処理を加えます。
def index
if params[:q] && params[:q].reject { |key, value| value.blank? }.present?
@q = User.ransack(search_params, activated_true: true)
@title = "Search Result"
else
@q = User.ransack(activated_true: true)
@title = "All users"
end
@users = @q.result.paginate(page: params[:page])
end
~
省略
~
private
def search_params
params.require(:q).permit(:name_cont)
end
params[:q][:name_cont]にユーザーが指定した検索ワードが含まれており、検索ワードの指定がない場合は全アクティブユーザーを取得します。
「モデル名.Ransack(検索条件)」の結果を「result」で取得します。
また、検索なしの時と検索ありの時でタイトルを変更しています。
Viewに戻って、index.html.erbに最初に作った_search_form.html.erbを挿入します。
<% provide(:title, @title) %>
<h1><%= @title %></h1>
<div class="row">
<div class="search_form">
<%= render 'users/search_form' %>
</div>
</div>
<%= will_paginate %>
<% unless @users.empty? %>
<ul class="users">
<%= render @users %>
</ul>
<% else %>
<p>
Couldn't find any user.<br>
Please check username you are looking for.
</p>
<% end %>
<%= will_paginate %>
検索結果が0の時にはメッセージを表示するようにしましたが、それ以外に特に気になる点はないと思います。
見た目を整えるために少しscssをいじって、実装は完了です。
.search_form {
overflow: auto;
margin: 10px;
float: right;
.input-group {
width: 300px;
.form-control {
width: 250px;
}
.btn {
width: 50px;
}
}
}
##テスト
最後にテストについて記載します。
まず、1.全ユーザー表示、2.検索(結果あり)、3.検索(結果なし)のパターンに分け、
1と2についてはタイトルとユーザー名のチェック、3についてはメッセージの確認を行うことにします。
テストはチュートリアルで作成していた、users_index_test.rbに追記しました。
~
省略
~
test "users search" do
log_in_as(@admin)
# All users
get users_path, params: {q: {name_cont: ""}}
User.paginate(page:1).each do |user|
assert_select 'a[href=?]', user_path(user), text:user.name
end
assert_select 'title', "All users | Ruby on Rails Tutorial Sample App"
# User search
get users_path, params: {q: {name_cont: "a"}}
q = User.ransack(name_cont: "a", activated_true: true)
q.result.paginate(page:1).each do |user|
assert_select 'a[href=?]', user_path(user), text:user.name
end
assert_select 'title', "Search Result | Ruby on Rails Tutorial Sample App"
# User search (no result)
get users_path, params: {q: {name_cont: "abcdefghijk"}}
assert_match "Couldn't find any user.", response.body
# Make sure the title is back to 'All users'
get users_path, params: {q: {name_cont: ""}}
assert_select 'title', "All users | Ruby on Rails Tutorial Sample App"
end
テストが通ったことを確認して終了です。
#最後に
Rails歴1週間もなく、以上の実装/テストも私の環境で動いたということに過ぎません。
修正点や指摘等ございましたら、ぜひコメントお願いいたします。
#参考記事
ユーザー検索では、下記の記事を参考にさせていただきました。
Ransackのススメ
https://qiita.com/nysalor/items/9a95d91f2b97a08b96b0
検索用のgem「ransack」を使ってみる
https://qiita.com/LuckOfWise/items/e020e896e71d47d0c6a4
Ransackで簡単に検索フォームを作る73のレシピ
http://nekorails.hatenablog.com/entry/2017/05/31/173925