Ruby on Rails チュートリアル 拡張機能 ( 2 .ユーザー検索・マイクロポスト検索機能追加)

拡張機能内容

今回は、追加機能の2つのうちの「 2. ユーザー検索・マイクロポスト検索機能追加」を紹介します。

(1)エラーメッセージの i18n対応(日本語対応)

(2) ユーザー検索・マイクロポスト検索機能追加

動作イメージ

https://yusuke-sampleapp2.herokuapp.com/

testユーザーでログインして動作が確認できます。

  • メールアドレス:test@gmail.com
  • パスワード: foobar

検索機能の機能概要

  • ユーザー一覧ページでユーザーの名前で検索できる。
  • ログイン後のHomeページ、ユーザーのプロフィールページでマイクロポストのコンテンツ内容で検索ができる。
  • 検索にヒットする場合は、フラッシュで検索した件数を画面に出力する。
  • 検索にヒットしない場合は、フラッシュでヒットしなかった旨を画面に出力し、デフォルトの検索結果を出力する
  • 検索したキーワードをハイライトで表示させる。

イメージ

ユーザー検索

f:id:mukkun0824:20200628190619g:plain

マイクロポスト検索

f:id:mukkun0824:20200628190635g:plain

実装

ユーザー検索機能の実装

検索結果の数をflashで表示するためのメソッド作成

 【中略】

    def count_flash(search_result)
      flash.now[:success] = t('.search result count',search_result_count: search_result.count)
    end

モデルの作成

 【中略】

  # 検索機能
  def self.search(keyword)
    if keyword.nil? || keyword.size > 0
      User.where(['name LIKE ?', "%#{keyword}%"])
    else
      return nil
    end
  end

 【中略】

コントローラーの作成

 【中略】

  def index
    #検索機能
    search_result = User.search(params[:keyword]) if params[:keyword]

    if search_result && !search_result.empty?
      @users = search_result.paginate(page: params[:page])
      @highlight_keyword = params[:keyword]
      count_flash(search_result)
    else
      @users = User.paginate(page: params[:page])
      flash.now[:info] = t('.not hit search') if params[:keyword]
    end
  end

 【中略】
 

ビューの作成。マイクロポスト検索でも使うのでパーシャル化しておく。

 【中略】
 
<div class="search">
  <%= form_with( url: yield(:path), method: :get, local: true) do |f|%>
      <%= f.text_field :keyword , class: 'form-control',placeholder: t('.search placeholder') %>
      <%= f.submit t('.search'), :name => nil , class: "btn btn-primary" %>
  <% end %>
</div>

【中略】

一覧ページから呼び込むようにする。

<% provide(:title, 'All users') %>
<h1>All users</h1>

<%= render 'shared/search' %>

<%= will_paginate %>

【中略】

ハイライト表示するようにユーザー一覧のビューも変更

<li>
  <%= gravatar_for user, size: 50 %>

  <%  u_link = link_to user.name, user %>

  <%= highlight(u_link,@highlight_keyword) %>
  <% if current_user.admin? && !current_user?(user) %>
    | <%= link_to "delete", user, method: :delete,
                                  data: { confirm: "You sure?" } %>

 【中略】

マイクロポスト検索機能の実装(ユーザープロフィールページ)

モデルの作成

 【中略】

  # 検索機能
  def self.search(keyword)
    if keyword.nil? || keyword.size > 0
      Micropost.where(['content LIKE ?', "%#{keyword}%"])
    else
      return nil
    end
  end

 【中略】

コントローラーの作成

 【中略】

  def show

    @user = User.find(params[:id])

    # 検索機能追加
    search_result = @user.microposts.search(params[:keyword]) if params[:keyword]

    if search_result && !search_result.empty?
      @microposts = search_result.paginate(page: params[:page])
      @highlight_keyword = params[:keyword]
      count_flash(search_result)
    else
      @microposts = @user.microposts.paginate(page: params[:page])
      flash.now[:info] = t('.not hit search') if params[:keyword]
    end

  end
 【中略】

ビューの作成 まずrenderを追加

 【中略】

  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>

        <%= render 'shared/search' %>

      <ol class="microposts">
        <%= render @microposts %>
      </ol>

 【中略】

ハイライト表示するようにマイクロポスト一覧のビューも変更

<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= highlight(micropost.content,@highlight_keyword) %>
    <%= image_tag micropost.display_image if micropost.image.attached? %>
  </span>

 【中略】

マイクロポスト検索機能の実装(ホームページ)

モデルは変更ありません。

コントローラーの作成

 【中略】

  def home
    if logged_in?
      @micropost  = current_user.microposts.build
      search_result = current_user.feed.search(params[:keyword]) if params[:keyword]

        if search_result && !search_result.empty?
          @feed_items = search_result.paginate(page: params[:page])
          @highlight_keyword = params[:keyword]
          count_flash(search_result)
        else
          @feed_items = current_user.feed.paginate(page: params[:page])
          flash.now[:info] = t('.not hit search') if params[:keyword]
        end
    end
  end

 【中略】

ビューの作成 renderを追加するだけです。あとはユーザープロフィールページのマイクロポスト一覧のところの実装がそのまま使えます。

 【中略】

    <div class="col-md-8">
      <h3>Micropost Feed</h3>
      <%= render 'shared/search' %>
      <%= render 'shared/feed' %>
    </div>

 【中略】

i18n対応

ja:
  static_pages:
    home:
      not hit search:       '検索条件にヒットしませんでした。'
      search result count:  '%{search_result_count}件ヒットしました。'
ja:
  users:
    index:
      not hit search:       '検索条件にヒットしませんでした。'
      search result count:  '%{search_result_count}件ヒットしました。'
    show:
      not hit search:       '検索条件にヒットしませんでした。'
      search result count:  '%{search_result_count}件ヒットしました。'
ja:
  shared:

 【中略】

    search:
      search placeholder:             '検索したい文字を入力してください'
      search:                         '検索'

以上で実装が完了です。

お役に立てれば幸いです。