Edited at

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


目的

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, :method => 'get' ) 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/se
arch' %>  <-- searchパーシャル呼出 -->
<%= render '
shared/feed' %>
</div>
</
div>


参考

Simple Search Form in Rails 5


関連記事

Ruby on Rails チュートリアル 完全攻略 概要と演習解答総まとめ

http://mochikichi.hatenablog.com/entry/rails_tutorial_guide