[RUBY] How to implement search function with rails (multiple columns are also supported)

Development environment

Mac OS Catalina 10.15.7 ruby 2.6 series rails 6.0 series


As a premise, I will explain using the application that I am currently making that can post articles as an example. I have a model name of post model. (For reference, please replace it for yourself.)

Routing settings

First, set up the routing. This time, it is necessary to define an action other than the basic action (index, new, create, show, edit, update, destroy) called search action, so set it using collection.


Rails.application.routes.draw do
  devise_for :users
  root to: "posts#index"
  resources :posts do
    resources :comments, only: [:create, :destroy]
    collection do
      get 'search'
  resources :users, only: :show

The collection allows you to customize the routing URL and the controller to be executed. You can also use member if you want to include the id in the routing.


member do
  get 'search'

Simply make the collection a member.

In my example this time, id is not needed, so I am using collection.

Search form creation

Now that we have the routing, let's create a search form to place in the view.


<%= form_with(url: search_posts_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "Search for posts", class: "search-input" %>
  <%= form.submit "Search", class: "search-btn" %>
<% end %>

I think there are many ways to write it, but I learned it like this.

The point is that it contains the path (search_posts_path) generated in the routing settings earlier (check the path name on the console), and don't forget method :: get.

In addition, the key name of the text_field of form_with is keyword.

Describe the search process in the model

Now, let's write the processing when actually searching in the model. At this time, I understand that I want to write it in the controller, but when defining a method that interacts with the table, try to write it in the model as much as possible. def self.search The following (excluding the end at the bottom) is the content described this time.


class Post < ApplicationRecord
  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to_active_hash :category
  belongs_to :user
  has_one_attached :image
  has_many :comments, dependent: :destroy

  with_options presence: true do
   validates :image
   validates :title
   validates :category_id, numericality: { other_than: 1 , message: "Is--Please choose from"} 

  def self.search(search)
    if search != ""
      Post.where(['title LIKE(?) OR explanation LIKE(?) OR animal_name LIKE(?)', "%#{search}%", "%#{search}%", "%#{search}%"])
      Post.includes(:user).order('created_at DESC')

As a basic writing style

Object name.where('Column name you want to search LIKE(?)', "%#{search}%")

When you want to search in multiple columns

Object name.where(['Column name you want to search LIKE(?) OR Column name you want to search LIKE(?)', "%#{search}%", "%#{search}%"])

You can do it like this. In my case, I want to search in 3 columns, so the description is as above.

Also, if the search field is empty in the if statement, the list of posts is displayed.

Controller description

Next, write the controller.


def search
  @posts = Post.search(params[:keyword])

I am using the search method defined in the model earlier. [: Keyword] in the argument params is the key name of text_field, which was set when the search form was created.

View creation

Finally, create the view referenced by the search action. I think that you can jump to the index page with render without making it separately.


<%= render "shared/header"%>

<%= form_with(url: search_posts_path, local: true, method: :get, class: "search-form") do |form| %>
  <%= form.text_field :keyword, placeholder: "Search for posts", class: "search-input" %>
  <%= form.submit "Search", class: "search-btn" %>
<% end %>

<% if @posts == [] %>
<h2 class = "seach-result">No results</h2>
<% else %>
<div class = "post-contents">
  <ul class = "post-list">
    <% @posts.each do |post| %>
    <li class = "list">
      <%= link_to post_path(post.id) do %>
      <%= image_tag post.image, class: "post-img" %>
      <h3 class='post-title'><%= post.title %></h3>
      <p class = "root-show">~ Click to see details ~</p>
      <% end %>
    <% end %>
<% end %>

<%= link_to new_post_path, class: 'post-btn' do %>
  <span class='post-btn-text'>Post</span>
<% end %>

<%= render  "shared/footer" %>

The above is how to implement the search function in rails. I'm glad if you can use it as a reference.

Recommended Posts

How to implement search function with rails (multiple columns are also supported)
How to search multiple columns with gem ransack
Rails learning How to implement search function using ActiveModel
How to implement search functionality in Rails
How to implement TextInputLayout with validation function
[Rails] Implement search function
[Rails] How to easily implement numbers with pull-down
[Rails] Implement User search function
[Rails] How to implement scraping
Implement search function with form_with
[Ruby on Rails] How to implement tagging / incremental search function for posts (without gem)
[Rails] Search from multiple columns + conditions with Gem and ransack
[Rails] How to implement star rating
How to get along with Rails
Implement a refined search function for multiple models without Rails5 gem.
I tried to implement the image preview function with Rails / jQuery
[Rails] How to use rails console with docker
Try to implement login function with Spring-Boot
[Swift] How to implement the countdown function
How to implement ranking functionality in Rails
How to implement image posting using rails
How to build Rails 6 environment with Docker
How to implement a slideshow using slick in Rails (one by one & multiple by one)
[Rails] How to search for records where each surname and given name are stored as DB columns
Rails API mode I tried to implement the keyword multiple search function using arrays and iterative processing.
How to save to multiple tables with one input
How to add / remove Ruby on Rails columns
[Rails6] How to connect the posting function generated by Scaffold with the user function generated by devise
[Swift] How to implement the LINE login function
[Rails] How to register multiple records in the intermediate table with many-to-many association
[swift5] How to implement the Twitter share function
[Rails] How to implement unit tests for models
How to implement the breadcrumb function using gretel
How to implement image posting function using Active Storage in Ruby on Rails
Try to implement login function with Spring Boot
[For beginners] How to implement the delete function
How to create multiple pull-down menus with ActiveHash
How to create search conditions involving multiple models
Let's make a search function with Rails (ransack)
[Rails] How to upload multiple images using Carrierwave
How to implement a like feature in Rails
[Swift] How to implement the fade-in / out function
How to build API with GraphQL and Rails
Implement search function with Rakuten Books (DVD) API
[Rails] How to build an environment with Docker
How to make a follow function in Rails
[Rails] How to easily introduce slick (slider function)
[Rails] How to search across columns of related models (parent or child) in ransack
[Rails / Uniqueness constraint] How to check model validation on the console / Uniqueness constraint for multiple columns
How to implement UICollectionView in Swift with code only
How to change the action with multiple submit buttons
How to make batch processing with Rails + Heroku configuration
Method summary to update multiple columns [Ruby on Rails]
How to implement login request processing (Rails / for beginners)
How to implement guest login in 5 minutes in rails portfolio
Implement post search function in Rails application (where method)
How to implement a like feature in Ajax in Rails
How to push an app developed with Rails to Github
[Rails, JS] How to implement asynchronous display of comments
How to make LINE messaging function made with Ruby
How to delete a new_record object built with Rails