[RUBY] Implement partial match search function without using Ransuck

I implemented the partial match search function without using Ransuck, so I will summarize it. This time, we will create a simple function that allows you to enter the name and email address and get the information of the corresponding user by partial match.

Example
Search for "no" in the name form and "" in the email address form
             ↓
Nobita Nobi [email protected]
It feels like output. I want to

From the conclusion, I will post the code first.

routes.rb


Rails.application.routes.draw do
  root 'users#index'
  resources :users
end

index.html


 <h1>Let's do a partial match search for Doraemon characters</h1>
<%= form_with(url: 'users', local: true, method: :get) do |f| %>
  <span class="small">Search target: Name Email address</span>
    <div>
      <%= f.label :name, 'name' %>
      <%= f.text_field :name , value: @search_params[:name] %>
    </div>
    <div>
      <%= f.label :email, 'mail address' %>
      <%= f.text_field :email, value: @search_params[:email] %>
    </div>
  <%= f.submit 'Search', class: 'btn btn-default' %>
<%end%>

<h1>search results</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: "Nobita Nobi",email: "[email protected]")
User.create!(name: "Takeshi Goda",email: "[email protected]")
User.create!(name: "Suneo Honekawa",email: "[email protected]")
User.create!(name: "Doraemon",email: "[email protected]")
User.create!(name: "Dorami-chan",email: "[email protected]")
User.create!(name: "Source Shizuka",email: "[email protected]")

I will explain each one. First from the explanation of view

index.html


 <h1>Let's do a partial match search for Doraemon characters</h1>
<%= form_with(url: 'users', local: true, method: :get) do |f| %>
  <span class="small">Search target: Name Email address</span>
    <div>
      <%= f.label :name, 'name' %>
      <%= f.text_field :name , value: @search_params[:name] %>
    </div>
    <div>
      <%= f.label :email, 'mail address' %>
      <%= f.text_field :email, value: @search_params[:email] %>
    </div>
  <%= f.submit 'Search', class: 'btn btn-default' %>
<%end%>

<h1>search results</h1>
  <% @users.each do |user| %>
    <%= user.name %>
    <%= user.email %>
  <% end %>

First of all, here

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

The search form uses form_with. The difference between form_tag and form_for is explained in an easy-to-understand manner at the following URL. https://qiita.com/hmmrjn/items/24f3b8eade206ace17e (Previously, form_tag was used when there was no related model, but form_for was used when there was a related model, but it is deprecated in rails 5.1. As a concrete example, I just want to use User information ( When searching) etc. is form_tag I want to register User information → I used form_for when the database to be registered existed. ) Form_with, which has been recommended since rails 5.1, divides the processing around it nicely and executes it. Also, Ajax for asynchronous communication is implemented by default. Since JS is not used this time, local: true is specified to invalidate the remote form, and the data is communicated by method: get in HTML format.

Next, let's look at the controller.

``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

The miso here is User.search (search_params). This is the search method, but the user model is scoped to the partial match search function. For the sent value, search returns a partial match to name and email. Then refer to 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

The search scope will fly to here, perform partial processing one by one, and then be returned to the controller. return if search_params.blank? By putting, even if no value is entered, the process will be stopped there and returned to the controller. If the search target is multiple such as: name: email like this time, params is iteratively processed and the search is returned one by one.

That's all for this time. If there was something different here, please point out more and more.

Recommended Posts

Implement partial match search function without using Ransuck
Implement user edit / update function without using devise
[Rails] Implement search function
Rails learning How to implement search function using ActiveModel
[Rails] Implement User search function
Search function using [rails] ransack
Implement category function using ancestory
Implement search function with form_with
Implement search functionality using LIKE clauses
Implement a refined search function for multiple models without Rails5 gem.
Implement share button in Rails 6 without using Gem
Implement the star five function using the for statement
Implement star rating function using Raty in Rails6
Implement the product category function using ancestry ① (Preparation)
How to implement the breadcrumb function using gretel
Flow to implement image posting function using ActiveStorage
Implement search function with Rakuten Books (DVD) API
[Ruby on Rails] How to implement tagging / incremental search function for posts (without gem)
Continued ・ Flow to implement image posting function using ActiveStorage
Implement post search function in Rails application (where method)
Implement test doubles in JUnit without using external libraries
[For Rails beginners] Implemented multiple search function without Gem
Try to implement using Rakuten product search API (easy)
Try to implement tagging function using rails and js