[RUBY] Establish a search bar in Rails ~ Join multiple tables to search

Introduction

This time, the post data (Post) is displayed by performing a keyword search on the search bar. In addition, we will join multiple tables and implement them so that they can be searched within that range.

Complete image

environment

MacOS 10.15.7 ruby 2.6.5 Ruby on Rails 6.0.0

Status of the author

table

searchFunction1.png

We have created a table with the user as "User", the post as "Post", the image as "Image", and the prefecture as "Prefecture" (seed data). (The contents of the table are simplified for posting)

The relations are as follows.

user.rb


has_many :posts, dependent: :destory

post.rb


belongs_to :user
belongs_to :prefecture

has_many :images, dependent: :destory


accepts_nested_attributes_for :images, allow_destroy: true

image.rb


belongs_to :post

mount_uploader :image, ImageUploader

prefecture.rb


has_many :posts

It looks like this. I have also introduced user and image, but this time I will omit the explanation because they are not related. Since prefecture has multiple posts, it is set as "has_many: posts". Since post belongs to prefecture, it will be "belongs_to: prefecture".

I will work!

(1) Search bar setting-function implementation

①-1 Creating a search bar

Create a search bar in this way.

erb:index.html.erb


<%= form_with(url: search_posts_path, local: true, method: :get, class: "rootpageSearchForm") do |form| %>
  <%= form.text_field :keyword, placeholder: "Enter a keyword", id: 'Search_Form', class: "rootpageSearchForm__content" %>
  <%= form.submit "Search", class: "rootpageSearchForm__bottum" %>
<% end %>

index.scss


.rootpageSearchForm {
  width: auto;
  &__content {
    width: 40vw;
    height: 30px;
    color: #000000;
    border-radius: 5px;
    border-color: #008bbb;
  }
  &__bottum {
    margin-left: 0.5vw;
    height: 30px;
    width: 150px;
    border-radius: 20px;
    background-color: #87cefa;
    border: none;
    box-shadow: 0 0 8px gray;
    color: #ffffff;
    -webkit-transition: all 0.3s ease;
    -moz-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
  }
  .rootpageSearchForm__bottum:hover {
    background-color: #00bfff;
  }
}

That is all. The completed image looks like this. searchForm.png

①-2 Creating a search action

Define a new search action in routes.rb. This time, we will define it in a nested form in the post action. Define it as follows.

routes.rb


Rails.application.routes.draw do
  resources :posts do
    collection do
      get 'search'
    end
  end
Some of the following are omitted...
end

This time, the corresponding posts are displayed as a list with the search keyword, so id is unnecessary.

collection do
  get 'search'
end

Is defined as.

If you need an id (such as a post detail page), define it using member instead of collection. The difference between collection and member is whether the URL has an id or not.

collection ・ ・ ・ The routing does not have an id. member ・ ・ ・ An id is attached to the routing.

①-3 Define search method in post model

class Post < ApplicationRecord
  ...Part of the above omitted
  def self.search(search)
    if search != ""
      Post.where('content LIKE(?) OR title LIKE(?), "%#{search}%", "%#{search}%")
    else
      Post.all
    end
  end
Some of the following are omitted...
end

Use the where method to get the" instance of the record that matches the condition "in the form of an array based on the condition described in the argument.

I use the LIKE clause to search for ambiguous strings.

String meaning
Arbitrary character string (including blank character string)
_ Any one character

Execution example

Execution example meaning
where('title LIKE(?)', "a%") Titles starting with a
where('title LIKE(?)', "%b") Titles ending in b
where('title LIKE(?)', "d_") Titles containing c
where('title LIKE(?)', "%b") Two-letter title starting with d
where('title LIKE(?)', "_e") Two-letter title ending in e

The argument search contains the parameters sent from the search form. Therefore, write if search! =" ", And the condition is that some value is entered in the search form.

If the search button is pressed when nothing is entered in the search form (empty state), the contents of search passed to the argument will be empty, so describe the processing in that case in the else statement. This time, as Post.all, all posts will be acquired and displayed.

__ Basically, the method related to the interaction with the table is put in the model! __

①-4 Describe the controller

Define a search action in posts_controller.rb.

posts_controller.rb


class PostsController < ApplicationController
  ...Part of the above omitted...
  def search
    @posts = Post.search(params[:keyword]).order(created_at: :desc)
  end
  ...Some of the following are omitted...

Write params [: keyword] in the argument of the search method and pass the search result.

Also, since the search results are arranged in the order of newest posts, it is described as order (created_at: desc).

①-5 Create search.html.erb and display the search results

After that, create search.html.erb to display the search result screen and it is completed.

ruby:search.html.erb


<div class="wrapper">
  <% @posts.each do |post| %>
    <div class='contents row'>
    ...Omitted below...
  <% end %>
</div>

①-6 Completed!

You can now view the search results using the search bar and keyword search. With the settings up to this point, the "content (post text)" and "title (post title)" of the Post table are being searched.

(2) Join other tables and add them to the search target.

This time, I would like to add "name (prefecture name)" in the Prefecture table to the search target so that you can also search by prefecture name.

We will add a description to the post model.

class Post < ApplicationRecord
  ...Part of the above omitted
  def self.search(search)
    if search != ""
      Post.joins(:prefecture).where('content LIKE(?) OR title LIKE(?) OR prefectures.name LIKE(?)', "%#{search}%", "%#{search}%", "%#{search}%")
    else
      Post.all
    end
  end
Some of the following are omitted...
end

The prefecture table is also added as joins (: prefecture) to be searched. The join method is a method` used when you want to join multiple tables into one. In this case, the post table and the prefecture table are joined and treated as one table.

In the argument part of the where method, OR prefectures.name LIKE (?)' Is added to specify the prefecture name as the search target. Add one "% # {search}% " for this amount and you're done.

Finally

Since I am a beginner, I would appreciate it if you could point out any mistakes. Thank you for watching until the end.

Recommended Posts

Establish a search bar in Rails ~ Join multiple tables to search
[Rails] Keyword search in multiple tables
How to write a date comparison search in Rails
Add a search function in Rails.
How to implement search functionality in Rails
How to insert a video in Rails
Steps to set a favicon in Rails
How to implement a slideshow using slick in Rails (one by one & multiple by one)
Convert to a tag to URL string in Rails
How to implement a like feature in Rails
How to easily create a pull-down in Rails
How to make a follow function in Rails
[Rails] How to search by multiple values ​​with LIKE
Throw raw SQL to a read replica in Rails
[How to insert a video in haml with Rails]
I want to define a function in Rails Console
[Rails 6] How to set a background image in Rails [CSS]
[Rails] How to load JavaScript in a specific view
[Rails] Creating a search box
How to use rails join
A story I was addicted to in Rails validation settings
How to display a graph in Ruby on Rails (LazyHighChart)
Use multiple checkboxes in Rails6!
Apply CSS to a specific View in Ruby on Rails
[Rails] A simple way to implement a self-introduction function in your profile
Implement a refined search function for multiple models without Rails5 gem.
How to rename a model with foreign key constraints in Rails
Preparing to create a Rails application
[Rails] How to write in Japanese
Create a new app in Rails
Implement a contact form in Rails
How to introduce jQuery in Rails 6
How to install Swiper in Rails
Change from SQLite3 to PostgreSQL in a new Ruby on Rails project
[Rails] I want to send data of different models in a form
How to implement search function with rails (multiple columns are also supported)
How to create a query using variables in GraphQL [Using Ruby on Rails]
[Rails] How to log in with a name by adding a devise name column
[Rails] I tried to implement a transaction that combines multiple DB processes
I want to select multiple items with a custom layout in Dialog
To create a Zip file while grouping database search results in Java
How to update user edits in Rails Devise without entering a password
What to do when "call'Hoge.connection' to establish a connection" appears on rails c
Do a prefix search in Swift's Firestore
When seeking multiple in a Java array
How to change app name in rails
How to use MySQL in Rails tutorial
Notation to put a variable in a string
[rails] How to create a partial template
How to implement ranking functionality in Rails
How to publish a library in jCenter
How to use credentials.yml.enc introduced in Rails 5.2
How to execute multiple commands in docker-compose.yml
Introduced # 10 devise_token_auth to build a bulletin board API with authentication authorization in Rails 6
[Rails / JavaScript / Ajax] I tried to create a like function in two ways.
[For rails beginners] Specify transition destination after logging in to multiple Devise models
[Rails] How to register multiple records in the intermediate table with many-to-many association
A memo to simply create a form using only HTML and CSS in Rails 6
[Rails] How to get rid of flash messages in a certain amount of time
How to make a judgment method to search for an arbitrary character in an array
How to store data simultaneously in a model associated with a nested form (Rails 6.0.0)