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

  • 10
    Like
  • 0
    Comment

目的

Ruby on Rails チュートリアル 5.0(第4版)で実装したサンプルアプリケーションを元に、検索機能を拡張します。

完成版アプリケーション

実際に検索機能を拡張したアプリケーションを見てみたい方はこちら。
https://fathomless-shore-36670.herokuapp.com/about

開発環境

・Rails 5.0
・cloud9

1.indexページにユーザ検索機能を実装する

最終的なソースコードと確認画面

[View]

users/index.html.erb
<% provide(:title, 'All users') %>
<h1>All users</h1>
<%= will_paginate %>

<!--  検索拡張機能  -->
<p>user search</p>
<%= form_tag(users_path) do %>
  <%= text_field_tag :search %>
  <%= submit_tag 'Search', :name => nil %>
<% end %>

<ul class="users">
  <%= render @users %>
</ul>
<%= will_paginate %>

[Controller]

users_controller.rb
class UsersController < ApplicationController
(中略)
  def index
    @users = User.where(activated: true).paginate(page: params[:page]).search(params[:search])
  end
(中略)
end

[Model]

models/user.rb
class User < ApplicationRecord
(中略)
  def self.search(search) #ここでのself.はUser.を意味する
    if search
      where(['name LIKE ?', "%#{search}%"]) #検索とnameの部分一致を表示。User.は省略
    else
      all #全て表示。User.は省略
    end
  end

  private
(中略)
end

[確認画面]
[検索前]
Users検索前.png

[検索後]
Users検索後.png

実装ステップ

手順を知りたい方は以下のブログを参照ください。
Ruby on Rails 検索機能拡張 (railsチュートリアル)

2.userプロフィールページにマイクロポスト検索機能を実装する

最終的なソースコードと確認画面

[View]

users/show.html.erb
<% provide(:title, @user.name) %>
<div class="row">
(中略)
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>

      <!--検索拡張機能  -->
      <p>content serch</p>
      <%= form_tag user_path, :method => 'get' do %>
        <p>
          <%= text_field_tag :search, params[:search] %>
          <%= submit_tag "Search", :name => nil %>
        </p>
      <% end %>

      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>

[Controller]

users_controller.rb
class UsersController < ApplicationController
(中略)
  def show
    @user = User.find(params[:id])
    # 検索拡張機能として.search(params[:search])を追加    
    @microposts = @user.microposts.paginate(page: params[:page]).search(params[:search])
  end
(中略)
end

[Model]

models/micropost.rb
class Micropost < ApplicationRecord
(中略)
  def self.search(search) #ここでのself.はMicropost.を意味する
    if search
      where(['content LIKE ?', "%#{search}%"]) #検索とcontentの部分一致を表示。Micropost.は省略。
    else
      all #全て表示。Micropost.は省略。
    end
  end

  private
(中略)
end

[確認画面]
[検索前]
Show検索前.png

[検索後]
Show検索後.png

実装ステップ

基本的には「1.indexページにユーザ検索機能を実装する」と同様のステップ。
[Model]のwhere(['content LIKE ?', "%#{search}%"])が"name"から"content"になっている点に注意。

3.Homeページにマイクロポスト検索機能を実装する

最終的なソースコードと確認画面

[View]

static_pages/home.html.erb
<% if logged_in? %>
  <%= render 'static_pages/user_logged_in' %>
<% else %>
  <%= render 'static_pages/user_not_logged_in' %>
<% end %>
static_pages/_user_logged_in.html.erb
<div class="row">
(中略)
  <div class="col-md-8">
    <h3>Micropost Feed</h3>

    <!--検索拡張機能  -->
    <p>content serch</p>
    <%= form_tag root_path, :method => 'get' do %>
      <p>
        <%= text_field_tag :search, params[:search] %>
        <%= submit_tag "Search", :name => nil %>
      </p>
    <% end %> 
    <%= render 'shared/feed' %>
  </div>
</div>

[Controller]

static_pages_controller.rb
class StaticPagesController < ApplicationController
  def home
    if logged_in?
      @micropost  = current_user.microposts.build
      # 検索拡張機能として.search(params[:search])を追加 
      @feed_items = current_user.feed.paginate(page: params[:page]).search(params[:search])
    end
  end
(中略)
end

[Model]
「2.userプロフィールページにマイクロポスト検索機能を実装する」から変更なし。

models/micropost.rb
class Micropost < ApplicationRecord
(中略)
  def self.search(search) #ここでのself.はMicropost.を意味する
    if search
      where(['content LIKE ?', "%#{search}%"]) #検索とcontentの部分一致を表示。Micropost.は省略。
    else
      all #全て表示。Micropost.は省略。
    end
  end

  private
(中略)
end

[確認画面]
[検索前]
Home検索前.png

[検索後]
Home検索後.png

実装ステップ

基本的には「1.indexページにユーザ検索機能を実装する」と同様のステップ。

4.リファクタリング

上記で検索機能を3つのviewページへ追加しました。
共通する部分が多いのでリファクタリングします。

users/_search.html.erb
<p><%= yield(:search_name) %></p>
<%= form_tag(yield(:path), method: :get) do %>
  <%= text_field_tag :search, params[:search] %>
  <%= submit_tag 'Search', :name => nil %>
<% end %>
users/index.html.erb
<% provide(:title, 'All users') %>
<% provide(:search_name, 'user search') %>
<% provide(:path, users_path) %>
<h1>All users</h1>

<%= will_paginate %>

<ul class="users">
  <%= render 'users/search' %>  <-- searchパーシャル呼出 -->
  <%= render @users %>
</ul>

<%= will_paginate %>
users/show.html.erb
<% provide(:title, @user.name) %>
<% provide(:search_name, 'content search') %>
<% provide(:path, user_path) %>
<div class="row">
(中略)
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>
      <%= render 'users/search' %>   <-- searchパーシャル呼出 -->
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
static_pages/_user_logged_in.html.erb
<% provide(:search_name, 'content search') %>
<% provide(:path, root_path) %>
  <div class="row">
(中略)
    <div class="col-md-8">
      <h3>Micropost Feed</h3>
      <%= render 'users/search' %>  <-- searchパーシャル呼出 -->  
      <%= render 'shared/feed' %>
    </div>
  </div>

参考

Simple Search Form in Rails 5

関連記事

Ruby on Rails チュートリアル 完全攻略 概要と演習解答総まとめ
http://mochikichi.hatenablog.com/entry/rails_tutorial_guide