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.)
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.
routes.rb
Rails.application.routes.draw do
devise_for :users
root to: "posts#index"
resources :posts do
resources :comments, only: [:create, :destroy]
collection do
get 'search'
end
end
resources :users, only: :show
end
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.
routes.rb
member do
get 'search'
end
Simply make the collection a member.
In my example this time, id is not needed, so I am using collection.
Now that we have the routing, let's create a search form to place in the view.
index.html.erb
<%= 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.
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.
post.rb
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"}
end
def self.search(search)
if search != ""
Post.where(['title LIKE(?) OR explanation LIKE(?) OR animal_name LIKE(?)', "%#{search}%", "%#{search}%", "%#{search}%"])
else
Post.includes(:user).order('created_at DESC')
end
end
end
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.
Next, write the controller.
posts_controller.rb
def search
@posts = Post.search(params[:keyword])
end
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.
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.
search.html.erb
<%= 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 %>
</li>
<% end %>
</ul>
</div>
<% 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