LoginSignup
28
43

More than 5 years have passed since last update.

Ruby on Rails チュートリアル 機能拡張1(ユーザー検索)

Last updated at Posted at 2018-01-07

Ruby on Rails チュートリアルについて

Ruby on Railsを勉強したいというと、まず紹介される有名なRailsのチュートリアル。
内容はハードですが、無料でRailsによるWebアプリケーション開発を楽しく学べます。

Ruby on Rails チュートリアル
https://railstutorial.jp/

Sample Appの拡張

チュートリアルの最後には、作成したSampleAppの拡張機能についていくつかのヒントが記載されています。
その中の以下の機能を順に実装していきます(途中で挫折するかも。。。)。
1. ユーザー検索
2. マイクロポスト検索
3. フォロワーの通知
4. 返信機能
5. メッセージ機能

ユーザー検索

今回は、1つ目のユーザー検索の実装を行います。
具体的には、全ユーザーを表示するページ(/users)上での、ユーザー名の検索、検索結果の表示を実現します。

環境と準備

ユーザー検索(および次回のマイクロポスト検索)では、Rails用の検索機能を簡単に実装できるRansack Gemを利用することにします。
Ransackは他のGemと同様に、Gemfileに追加し、bundle installします。

モジュール バージョン
Rails 5.1.2
Ruby 2.3.1
Ransack 1.8.4

実装

まず、ユーザー検索用のフォームを作成します。

app/views/users/_search_form.html.erb
<%= 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アクションに処理を加えます。

app/controllers/users_controller
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を挿入します。

app/views/users/index.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をいじって、実装は完了です。

app/assets/stylesheets/custom.scss
.search_form {
  overflow: auto;
  margin: 10px;
  float: right;
  .input-group {
    width: 300px;
    .form-control {
      width: 250px;
    }
    .btn {
      width: 50px;
    }
  }
}

見た目はこんな感じです。
全ユーザー
alluser.png

検索結果
searchresult.png

検索結果なし
noresult.png

テスト

最後にテストについて記載します。
まず、1.全ユーザー表示、2.検索(結果あり)、3.検索(結果なし)のパターンに分け、
1と2についてはタイトルとユーザー名のチェック、3についてはメッセージの確認を行うことにします。
テストはチュートリアルで作成していた、users_index_test.rbに追記しました。

test/integration/user_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

28
43
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
28
43