LoginSignup
1
0

More than 3 years have passed since last update.

部分一致検索機能の実装をRansuckを使用せず行う

Last updated at Posted at 2020-10-10

部分一致検索機能の実装をRansuckを使用せず行ったのでまとめていく。
今回は名前、メールアドレスを入力するとそれに部分一致で該当するユーザーの情報を取得できるという簡単な機能を作る。

例 
名前フォームに「の」 メールアドレスフォームに「  」で検索
             ↓
野比 のび太 nobinobi@example.com
が出力するみたいな感じ。にしたい。

結論からということでまずはコード載せますね。

routes.rb
Rails.application.routes.draw do
  root 'users#index'
  resources :users
end
index.html
 <h1>ドラえもんキャラを部分一致検索してみよう</h1>
<%= form_with(url: 'users', local: true, method: :get) do |f| %>
  <span class="small">検索対象: 名前 メールアドレス</span>
    <div>
      <%= f.label :name, '名前' %>
      <%= f.text_field :name , value: @search_params[:name] %>
    </div>
    <div>
      <%= f.label :email, 'メールアドレス' %>
      <%= f.text_field :email, value: @search_params[:email] %>
    </div>
  <%= f.submit '検索', class: 'btn btn-default' %>
<%end%>

<h1>検索結果</h1>
  <% @users.each do |user| %>
    <%= user.name %>
    <%= user.email %>
  <% end %>
users_controller.rb
class UsersController < ApplicationController
  def index
    @search_params = search_params
    @users = User.search(search_params)
  end

  private

  def search_params
    params.permit( :name, :email  )
  end
end
user.rb
class User < ApplicationRecord
  scope :search, -> (search_params) do
    return if search_params.blank?
      name_like(search_params[:name] )
      .email_like(search_params[:email])
    end
  scope :name_like, -> (name){where("name LIKE ?" ,"%#{name}%")}
  scope :email_like, -> (email){where("email LIKE ?", "%#{email}%")}
end
schema.rb

ActiveRecord::Schema.define(version: 2020_10_10_011424) do

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

seeds.rb
User.create!(name: "野比 のび太",email: "nobinobi@example.com")
User.create!(name: "剛田 武",email: "soulmate@example.com")
User.create!(name: "骨川 スネ夫",email: "kanemoti@example.com")
User.create!(name: "ドラえもん",email: "dora@example.com")
User.create!(name: "ドラミちゃん",email: "dorami@example.com")
User.create!(name: "源 しずか",email: "piano@example.com")

一個一個説明していきます。
まずviewの説明から

index.html
 <h1>ドラえもんキャラを部分一致検索してみよう</h1>
<%= form_with(url: 'users', local: true, method: :get) do |f| %>
  <span class="small">検索対象: 名前 メールアドレス</span>
    <div>
      <%= f.label :name, '名前' %>
      <%= f.text_field :name , value: @search_params[:name] %>
    </div>
    <div>
      <%= f.label :email, 'メールアドレス' %>
      <%= f.text_field :email, value: @search_params[:email] %>
    </div>
  <%= f.submit '検索', class: 'btn btn-default' %>
<%end%>

<h1>検索結果</h1>
  <% @users.each do |user| %>
    <%= user.name %>
    <%= user.email %>
  <% end %>

まずここなのですが

<%= form_with(scope: :search ,url: 'users', local: true, method: :get) do |f| %>

検索フォームはform_withを使用しています。form_tag と form_forとの違いは下記URLにわかりやすく説明されています。
https://qiita.com/hmmrjn/items/24f3b8eade206ace17e
(以前は関連するモデルがなかったときは form_tag 関連するモデルがある時は form_forを使用していましたがrails5.1で非推奨となっています。具体例として挙げるとUser情報を使いたいだけ(検索時)などはform_tag
User情報を登録したい→登録されるデータベースが存在している時はform_forを使用していた。)
rails5.1以降より推奨されているform_withはそこら辺の処理をうまい感じに切り分けて実行してくれます。またデフォルトで非同期通信のAjaxが実装されてます。今回はJSは使用しない実装なので、リモートフォームを無効にするため local: true と指定し、HTML形式でデータをmethod: get にて通信しています。

続いてコントローラーを見ていきましょう。

users_controller.rb
class UsersController < ApplicationController
  def index
    @search_params = search_params
    @users = User.search(search_params)
  end

  private

  def search_params
    params.permit( :name, :email  )
  end
end

ここでのみそは User.search(search_params) です。こちらのsearchメソッドなのですがUsermodelの方に部分一致検索機能をscopeしています。送られた値に対しsearchでnameとemailに部分一致処理をし返します。続いてmodelを参照してください。

user.rb
class User < ApplicationRecord
  scope :search, -> (search_params) do
    return if search_params.blank?
      name_like(search_params[:name] )
      .email_like(search_params[:email])
    end
  scope :name_like, -> (name){where("name LIKE ?" ,"%#{name}%")}
  scope :email_like, -> (email){where("email LIKE ?", "%#{email}%")}
end

searchスコープはこちらに飛んで一つ一つ部分処理をした後コントローラに返されます。
return if search_params.blank?
を入れておく事で仮に何も値がはいっていなくても処理をそこで止めてコントローラに返します。
検索対象が今回のように:name :emailと複数である場合はparamsを繰り返し処理とし一つ一つ検索を返すようにします。

今回は以上となります。
もしここは違うなどありましたどんどん指摘しください。

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