0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Railsチュートリアル にユーザー検索を実装してみた

Posted at

#行ったこと
Railsチュートリアル6.0を完走し、最後に拡張機能としてユーザー検索を実装した
自分の勉強のためにアウトプットしています。

#完成版はこちら
https://damp-spire-94870.herokuapp.com/users?search=e&commit=%E6%A4%9C%E7%B4%A2

#参考記事
https://qiita.com/mochikichi321/items/5c9630c5d87b47130942
https://qiita.com/s-yank/items/964e82bcecaa659caa2d

#手順(チュートリアル14章まで終わっていることが前提)

##1現時点のコード確認

users/index.html.erb

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

#ここへ検索拡張機能追加予定

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

class UsersController < ApplicationController
(中略)
  def index
    @users = User.where(activated: true,).paginate(page: params[:page])
#activatedがtrueの物だけ探して、paginateしている
  end
(中略)
end

##2まずは、ビューを整える

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

<%= will_paginate %>

#検索窓
<%= form_with(url:users_path, :method => 'get',local: true) do |form|  %>
  <%= form.label :ユーザー検索 %>
  <%= form.text_field :search,class:'form-control' %>
  <%= form.submit '検索' , class: "btn btn-primary" %>
<% end %>

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

<%= will_paginate %>

ここでつまずいたので解説すると、

<%= form_with(url:users_path, :method => 'get',local: true) do |form|  %>
  <%= form.label :ユーザー検索 %>
  <%= form.text_field :search,class:'form-control' %>
  <%= form.submit '検索' , class: "btn btn-primary" %>
<% end %>

form_withはform_tagが非推奨になったことから、railsチュートリアルでも利用していたタグ。
url,methodlocalを指定する。
method => 'get'を指定しないと、form_withがデフォルトでmethod post送信なのでうまく処理されないらしい
local:trueを指定しないと、form_withがデフォルトでremote: trueとなり、送信したデータがAjax通信で処理されます
その場合、検索ボタンを押した時に画面が遷移しないため、indexの一覧画面の情報が更新されなくなってしまう。

classの指定はbootstrapを反映させるためです。

##3コントローラー側
コントローラー側はこちらの記事を参考(マルパクリ)で
https://qiita.com/mochikichi321/items/5c9630c5d87b47130942

users_controller.rb

class UsersController < ApplicationController
(中略)
  def index
    #条件分岐
    @users = if params[:search]
      #searchされた場合は、原文+.where('name LIKE ?', "%#{params[:search]}%")を実行
      User.where(activated: true).paginate(page: params[:page]).where('name LIKE ?', "%#{params[:search]}%")
    else
      #searchされていない場合は、原文そのまま
      User.where(activated: true).paginate(page: params[:page])
    end
  end
(中略)
end

こうなります

where('name LIKE ?', "%#{params[:search]}%")

の部分は、SQLの文法で
https://techacademy.jp/magazine/22330
を参考にすると

User.where("name LIKE ?", "%hana%")

LIKE句はSQLの検索を行うための演算子
name LIKEと書くことでnameカラムを検索、という意味になる

?は次の引数"%hana%"を受け取る場所になります。最終的にname LIKE "%hana%"という風になるということです。%は任意の文字列を指します。

つまり、nameカラムにhanaを含むレコードを抽出する、という処理になるらしい。

最終的に、

where('name LIKE ?', "%#{params[:search]}%")

params[:search]で受け取った文字式展開を受け取り、検索すると言う事になります。

これで実装されるはずですがリファクタリングもしておきます。

##4リファクタリング

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_controller.rb

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

これでform_withを使った検索の実装は終わりです

後日、こちらのテストも書いてみたいと思います。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?