[RUBY] Implement a refined search function for multiple models without Rails5 gem.

Contents to be implemented

Implement pull-down condition selection of exact match, prefix match, suffix match, and partial match with the two models you want to search in the search form. (Reference image) http://drive.google.com/uc?export=view&id=1vsAOuXvOIV1IzDxaPhUJ0rLL0V0AgPUC

<img src=https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F700999%2Fa126f999-9e5e-f80c-913d-e7ee2c86652a.gif?ixlib=rb-1.2.2&auto=format&gif-q=60&q=75&s=b85b97e43acfbe1b95ec86c20570bce4>

Implementation

Since we will not create a model this time, we will create only the controller and view Execute rails g controller Seraches search with the command. Add get'users / search'=>'searches # search' to routes.rb

First of all, set up a search form.

views/View I want to fill in a search form


<%= form_tag(users_search_path, method: :get) do %>
    <%= text_field_tag 'search[content]' %>
   	<%= select_tag 'search[model]', options_for_select({ "user" => "user", "tag" => "muscle" }) %>
   	<%= select_tag 'search[how]', options_for_select({ "Perfect matching" => "match", "Prefix match" => "forward", "Backward match" => "backward", "Partial Match" => "partical"  }) %>
    <%= submit_tag 'Search', class: "btn btn-primary" %>
  <% end %>

Then implement the controller

users/searches_controller.rb



def search
    @content = params['search']['content']
    @how = params['search']['how']
    @model = params['search']['model']
    @datas = search_for(@how, @model, @content)
end

private

  def match(model, content)
    if model == 'user'
      User.where(name: content)
    elsif model == 'muscle'
      Muscle.where(work_tag: content)
    end
  end

  def forward(model, content)
    if model == 'user'
      User.where('name LIKE ?', "#{content}%")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "#{content}%")
    end
  end

  def backward(model, content)
    if model == 'user'
      User.where('name LIKE ?', "%#{content}")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "%#{content}")
    end
  end

  def partical(model, content)
    if model == 'user'
      User.where('name LIKE ?', "%#{content}%")
    elsif model == 'muscle'
      Muscle.where('work_tag LIKE ?', "%#{content}%")
    end
  end

  def search_for(how, model, content)
    case how
    when 'match'
      match(model, content)
    when 'forward'
      forward(model, content)
    when 'backward'
      backward(model, content)
    when 'partical'
      partical(model, content)
    end
  end
end

Description of controller

Since I am searching the work_tag column of the Muscles table and the name column of the Users table, please change them for each individual.

    @content = params['search']['content']
    @how = params['search']['how']
    @model = params['search']['model']
    @datas = search_for(@how, @model, @content)

Separated commentary

-First of all, when the user executes a search from the view where form_tag is installed, searches_controller is called and the search contents sent from the view are stored in @content. ・ Store conditions such as exact match sent from view in @how ・ Store the model you want to search, such as the user sent from view, in @model -Invoke the search_for method to @datas and pass (@how, @model, @content) as an argument.

Look at search_for

def search_for(how, model, content)
    case how
    when 'match'
      match(model, content)
    when 'forward'
      forward(model, content)
    when 'backward'
      backward(model, content)
    when 'partical'
      partical(model, content)
    end
end

'Match' is an exact match, and 'partcial' is a partial match, as you can see by looking at form_tag. -When the content of how is `'match'in the case statement, the match method is called in the serach_for method.

Let's look at the match method

def match(model, content)
    if model == 'user'
      User.where(name: content)
    elsif model == 'muscle'
      Muscle.where(work_tag: content)
    end
  end

-In the called match method, the contents of the stored model are conditional depending on whether it is user or muscle. -Of course, since it is an exact match, in the case of User, everything that matches the content and name columns sent from the form in ʻUser.where` is acquired -The match method is now executed and the result is stored in @datas.

Display search results

rails:views/seaches/searche.html.erb



<% if @model == "user" %>
<div class="row  justify-content-center">
  <h2>User list</h2>
</div>
<div class="row  justify-content-center">
  <% @datas.each do |datas| %>
  <table class="table table-striped table-bordered">
   	<thead>
		<tr>
			<th>username</th>
	        </tr>
       </thead>
   	<tbody>
	   	<tr>
	    	<td>
	    	  <%= link_to datas.name, user_path(datas.id) %>
	    	</td>
	    </tr>
	</tbody>
	</table>
	<% end %>
</div>

<% elsif @model == "muscle"%>
<div class="row  justify-content-center">
<table class="table table-striped table-bordered">
   	<thead>
		<tr>
			<th>Tag list</th>
	        </tr>
       </thead>
   	<tbody>
	   	<tr>
	    	<td>
	    		<%= link_to datas.work_tag, muscle_path(datas.id) %>
	    	</td>
	    </tr>
	</tbody>
	</table>
</div>
<% else %>
<% end %>

-Change the html to be displayed depending on whether the model is user or muscle in the if statement. -Turn the items stored in @datas with each do to display them in a list.

Finally

If you understand the method, you can easily implement it without gem. Please comment if there is something missing or unclear.

Recommended Posts

Implement a refined search function for multiple models without Rails5 gem.
[For Rails beginners] Implemented multiple search function without Gem
[Ruby on Rails] How to implement tagging / incremental search function for posts (without gem)
[Rails] Implement search function
[Rails] Implement User search function
[Rails] Implemented a pull-down search function for Active Hash data
Add a search function in Rails.
[Rails] Manage multiple models using devise gem
How to implement search function with rails (multiple columns are also supported)
Implement share button in Rails 6 without using Gem
Implement partial match search function without using Ransuck
[Rails] How to implement unit tests for models
Let's make a search function with Rails (ransack)
Implement post search function in Rails application (where method)
[Rails 6.0] I implemented a tag search function (a function to narrow down by tags) [no gem]
Rails search function implementation
Rails learning How to implement search function using ActiveModel
[Rails] Implementation of tagging function using intermediate table (without Gem)
[Rails] Implement event end function (logical deletion) using paranoia (gem)
Establish a search bar in Rails ~ Join multiple tables to search
[Rails] Search from multiple columns + conditions with Gem and ransack
Rails fuzzy search function implementation
Search function using [rails] ransack
Implement follow function in Rails
[Rails 6] Implementation of search function
[Rails] Creating a search box
[Rails] Implement image posting function
Implement search function with form_with
[Rails] A simple way to implement a self-introduction function in your profile
I made a reply function for the Rails Tutorial extension (Part 1)
I made a reply function for the Rails Tutorial extension (Part 5):
Rails API mode I tried to implement the keyword multiple search function using arrays and iterative processing.
[Rails] Keyword search in multiple tables
[Rails] List instances of multiple models
Implement simple login function in Rails
Implement a like feature for posts
[Swift 5] Implement UI for review function
Implement a contact form in Rails
[Rails] gem ancestry category function implementation
Implement CSV download function in Rails
How to implement a slideshow using slick in Rails (one by one & multiple by one)
[Rails] I tried to implement a transaction that combines multiple DB processes
[Rails] Implement the product purchase function with a credit card registered with PAY.JP
I made a reply function for Rails Tutorial extension (Part 2): Change model